此包含SVG的HTML:
queue()
.defer(d3.json, "/data")
.await(makeGraphs);
function makeGraphs(error, recordsJson) {
//Clean data
var records = recordsJson;
var dateFormat = d3.time.format("%Y-%m-%d %H:%M:%S");
records.forEach(function(d) {
d["timestamp"] = dateFormat.parse(d["timestamp"]);
d["timestamp"].setMinutes(0);
d["timestamp"].setSeconds(0);
d["longitude"] = +d["longitude"];
d["latitude"] = +d["latitude"];
});
//Create a Crossfilter instance
var ndx = crossfilter(records);
//Define Dimensions
var dateDim = ndx.dimension(function(d) { return d["timestamp"]; });
var genderDim = ndx.dimension(function(d) { return d["gender"]; });
var ageSegmentDim = ndx.dimension(function(d) { return d["age_segment"]; });
var phoneBrandDim = ndx.dimension(function(d) { return d["phone_brand_en"]; });
var locationdDim = ndx.dimension(function(d) { return d["location"]; });
var allDim = ndx.dimension(function(d) {return d;});
//Group Data
var numRecordsByDate = dateDim.group();
var genderGroup = genderDim.group();
var ageSegmentGroup = ageSegmentDim.group();
var phoneBrandGroup = phoneBrandDim.group();
var locationGroup = locationdDim.group();
var all = ndx.groupAll();
//Define values (to be used in charts)
var minDate = dateDim.bottom(1)[0]["timestamp"];
var maxDate = dateDim.top(1)[0]["timestamp"];
//Charts
var numberRecordsND = dc.numberDisplay("#number-records-nd");
var timeChart = dc.barChart("#time-chart");
var genderChart = dc.rowChart("#gender-row-chart");
var ageSegmentChart = dc.rowChart("#age-segment-row-chart");
var phoneBrandChart = dc.rowChart("#phone-brand-row-chart");
var locationChart = dc.rowChart("#location-row-chart");
numberRecordsND
.formatNumber(d3.format("d"))
.valueAccessor(function(d){return d; })
.group(all);
timeChart
.width(650)
.height(140)
.margins({top: 10, right: 50, bottom: 20, left: 20})
.dimension(dateDim)
.group(numRecordsByDate)
.transitionDuration(500)
.x(d3.time.scale().domain([minDate, maxDate]))
.elasticY(true)
.yAxis().ticks(4);
genderChart
.width(300)
.height(100)
.dimension(genderDim)
.group(genderGroup)
.ordering(function(d) { return -d.value })
.colors(['#6baed6'])
.elasticX(true)
.xAxis().ticks(4);
ageSegmentChart
.width(300)
.height(150)
.dimension(ageSegmentDim)
.group(ageSegmentGroup)
.colors(['#6baed6'])
.elasticX(true)
.labelOffsetY(10)
.xAxis().ticks(4);
phoneBrandChart
.width(300)
.height(310)
.dimension(phoneBrandDim)
.group(phoneBrandGroup)
.ordering(function(d) { return -d.value })
.colors(['#6baed6'])
.elasticX(true)
.xAxis().ticks(4);
locationChart
.width(200)
.height(510)
.dimension(locationdDim)
.group(locationGroup)
.ordering(function(d) { return -d.value })
.colors(['#6baed6'])
.elasticX(true)
.labelOffsetY(10)
.xAxis().ticks(4);
var map = L.map('map');
var drawMap = function(){
map.setView([31.75, 110], 4);
mapLink = '<a href="http://openstreetmap.org">OpenStreetMap</a>';
L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© ' + mapLink + ' Contributors',
maxZoom: 15,
}).addTo(map);
//HeatMap
var geoData = [];
_.each(allDim.top(Infinity), function (d) {
geoData.push([d["latitude"], d["longitude"], 1]);
});
var heat = L.heatLayer(geoData,{
radius: 10,
blur: 20,
maxZoom: 1,
}).addTo(map);
};
//Draw Map
drawMap();
//Update the heatmap if any dc chart get filtered
dcCharts = [timeChart, genderChart, ageSegmentChart, phoneBrandChart, locationChart];
_.each(dcCharts, function (dcChart) {
dcChart.on("filtered", function (chart, filter) {
map.eachLayer(function (layer) {
map.removeLayer(layer)
});
drawMap();
});
});
dc.renderAll();
};
和这个简单的jQuery click事件处理程序:
{% extends "base.html" %}
{% block content %}
<body class="application">
<div class="container-fluid">
<div class="row">
<div class="col-sm-6">
<div class="row">
<!-- Time Chart -->
<div class="col-sm-12">
<div class="chart-wrapper">
<div class="chart-title">
Congestion Key Issues
</div>
<div class="chart-stage">
<div id="time-chart"></div>
</div>
</div>
</div>
<!-- Time Chart -->
<!-- Brand -->
<div class="col-sm-6">
<div class="chart-wrapper">
<div class="chart-title">
Heatmap
</div>
<div class="chart-stage">
<div id="phone-brand-row-chart"></div>
</div>
</div>
</div>
<!-- Brand -->
<div class="col-sm-6">
<div class="row">
<!-- Gender -->
<div class="col-sm-12">
<div class="chart-wrapper">
<div class="chart-title">
Occupancy
</div>
<div class="chart-stage">
<div id="gender-row-chart"></div>
</div>
</div>
</div>
</div>
<!-- Gender -->
<!-- Age Segment -->
<div class="row">
<div class="col-sm-12">
<div class="chart-wrapper">
<div class="chart-title">
Speed
</div>
<div class="chart-stage">
<div id="age-segment-row-chart"></div>
</div>
</div>
</div>
<!-- Age Segment -->
</div>
</div>
</div>
</div>
<div class="col-sm-2">
<div class="row">
<!-- Chinese Province -->
<div class="col-sm-12">
<div class="chart-wrapper">
<div class="chart-title">
Suburb
</div>
<div class="chart-stage">
<div id="location-row-chart"></div>
</div>
</div>
</div>
<!-- Chinese Province -->
</div>
</div>
<div class="col-sm-4">
<div class="row">
<!-- Map -->
<div class="col-sm-12">
<div class="chart-wrapper">
<div class="chart-title">
Map
</div>
<div class="chart-stage">
<div id="map" style="width: 400px; height: 380px"></div>
</div>
</div>
</div>
<!-- Map -->
</div>
<div class="row">
<!-- Number of events -->
<div class="col-sm-12">
<div class="chart-wrapper">
<div class="chart-title">
Speed Observation
</div>
<div class="chart-stage">
<div id="number-records-nd"></div>
</div>
</div>
</div>
<!-- Number of events -->
</div>
</div>
</div>
</div>
</body>
{% endblock %}
如下所示:https://jsfiddle.net/1ht0L8y6/6/在不同的浏览器中具有不同的行为:
Chrome浏览器:无论我在SVG中的哪个位置单击,坐标均基于SVG元素的左上角。这是我想要的行为。
Firefox :坐标基于我所处元素的左上角,这些元素可能是SVG,多边形或文本。
IE和Edge:
from flask_sqlalchemy import SQLAlchemy
from flask import (Flask, request, session, g, redirect, url_for, abort,
render_template, flash)
import pandas as pd
from shapely.geometry import Point, shape
import json
data_path = './input/'
n_samples = 30000
def get_age_segment(age):
if age <= 22:
return '22-'
elif age <= 26:
return '23-26'
elif age <= 28:
return '27-28'
elif age <= 32:
return '29-32'
elif age <= 38:
return '33-38'
else:
return '39+'
def get_location(longitude, latitude, provinces_json):
point = Point(longitude, latitude)
for record in provinces_json['features']:
polygon = shape(record['geometry'])
if polygon.contains(point):
return record['properties']['name']
return 'other'
with open(data_path + '/geojson/china_provinces_en.json') as data_file:
provinces_json = json.load(data_file)
app = Flask(__name__) # create the application instance :)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///streams.sqlite3'
db = SQLAlchemy(app)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/Map')
def Map():
return render_template('map.html')
@app.route("/data")
def get_data():
gen_age_tr = pd.read_csv(data_path + 'gender_age_train.csv')
ev = pd.read_csv(data_path + 'events.csv')
ph_br_dev_model = pd.read_csv(data_path + 'phone_brand_device_model.csv')
df = gen_age_tr.merge(ev, how='left', on='device_id')
df = df.merge(ph_br_dev_model, how='left', on='device_id')
#Get n_samples records
df = df[df['longitude'] != 0].sample(n=n_samples)
top_10_brands_en = {'华为':'Huawei', '小米':'Xiaomi', '三星':'Samsung', 'vivo':'vivo', 'OPPO':'OPPO',
'魅族':'Meizu', '酷派':'Coolpad', '乐视':'LeEco', '联想':'Lenovo', 'HTC':'HTC'}
df['phone_brand_en'] = df['phone_brand'].apply(lambda phone_brand: top_10_brands_en[phone_brand]
if (phone_brand in top_10_brands_en) else 'Other')
df['age_segment'] = df['age'].apply(lambda age: get_age_segment(age))
df['location'] = df.apply(lambda row: get_location(row['longitude'], row['latitude'], provinces_json), axis=1)
cols_to_keep = ['timestamp', 'longitude', 'latitude', 'phone_brand_en', 'gender', 'age_segment', 'location']
df_clean = df[cols_to_keep].dropna()
return df_clean.to_json(orient='records')
"""
@app.route('/Analytics')
def Analytics():
return render_template('analytics.html')
"""
组的原点及其偏移量<div class="container">
<div class="spacer"></div>
<svg>
<g id="polygonGroup" transform="translate(80, 50)">
<polygon points="-60,-10 -35,-30 -10,-10 -10,30 -60,30"></polygon>
<polygon points="10,-10 35,-30 60,-10 60,30 10,30"></polygon>
<polygon class="origin" points="-4,0 0,4 4,0 0,-4"></polygon>
</g>
<g id="textGroup" transform="translate(80, 50)">
<text x="-35" y="10">Text</text>
<text x="35" y="10">Text</text>
</g>
</svg>
</div>
(即黑钻石)。负坐标可以这样
与Chrome或Firefox不同。什么是可靠的跨浏览器获取点击坐标的方法?
答案 0 :(得分:4)
我在您的代码中添加了一个检测SVG中鼠标位置的功能。
let svg = document.querySelector('svg')
function clicked(event) {
let m = oMousePosSVG(event);
console.log(m.x,m.y);
}
svg.addEventListener("click", clicked)
function oMousePosSVG(e) {
var p = svg.createSVGPoint();
p.x = e.clientX;
p.y = e.clientY;
var ctm = svg.getScreenCTM().inverse();
var p = p.matrixTransform(ctm);
return p;
}
svg{border:1px solid}
<div class="container">
<div class="spacer"></div>
<svg>
<g id="polygonGroup" transform="translate(80, 50)">
<polygon points="-60,-10 -35,-30 -10,-10 -10,30 -60,30"></polygon>
<polygon points="10,-10 35,-30 60,-10 60,30 10,30"></polygon>
<polygon class="origin" points="-4,0 0,4 4,0 0,-4"></polygon>
</g>
<g id="textGroup" transform="translate(80, 50)" fill="red">
<text x="-35" y="10">Text</text>
<text x="35" y="10">Text</text>
</g>
</svg>
</div>
要了解有关SVG中鼠标检测的更多信息,我推荐这本书:Using SVG with CSS3 and HTML5: Vector Graphics for Web Design
希望对您有帮助。