我有一些d3 svg元素,其中将坐标x,y的列表作为属性传递,并将它们绘制在svg映射上。像下面的例子一样:
var svg = iniMarker().append("g")
.attr("data-lineData", JSON.stringify(lineData))
//Function to draw line
var lineFunction = d3.svg.line()
.x(function (d) { return d.x; })
.y(function (d) { return d.y; });
生成的路径结构如下:
<path d="M1100,850L1180,800" class="pPath" stroke-dasharray="94.33981323242188 94.33981323242188" stroke-dashoffset="0"></path>
<path d="M1180,800L1280,800" class="pPath" stroke-dasharray="100 100" stroke-dashoffset="0"></path>
<path d="M1280,800L1380,800" class="pPath" stroke-dasharray="100 100" stroke-dashoffset="0"></path>
在此直线路径的顶部还有一个圆,它以直线数据坐标值作为输入:
var circle = svg.append("circle")
.attr("r", 10)
.attr("fill", "#fff")
.attr("class", "marker")
.attr("transform", function () {
return "translate(" + lineData[0].x + "," + lineData[0].y + ")";
});
我获取坐标信息的数据以这种格式存储:
var DataSet = [{
"id": "",
"isActive": true,
"personId": "p1",
"name": "test",
"lineData": [
{ "timestamp": "2018/09/15 10:00:05 AM", "x": 1100, "y": 950 }]
现在,我需要在精确叠加在svg地图上的画布地图上表示从此坐标列表中获取的每个点。 在这种情况下,问题在于列表的svg坐标与画布坐标的位置不匹配。
实际上,如果我尝试使用以下功能生成一些画布坐标点:
document.getElementById("canv").onclick = function (e) {
var localX = e.clientX - e.target.offsetLeft;
var localY = e.clientY - e.target.offsetTop;
}
然后onclick
事件的坐标与我从DataSet obj作为位置的svg坐标有很大不同。
实际上,为了匹配它们,我只是试图将DataSet obj传递给一个函数,以便获取svg坐标并将其绘制在画布地图上,如下所示:
DataSet.map(function (m) { if(m.isActive) return m.lineData; else return []; }).forEach(f => data = data.concat(f));
data.forEach(e => {
//here I call another function for plot the svg coordinates as points on the canvas map
});
但是很明显,我需要先转换它们才能正确匹配。
按照@enxaneta的建议,我需要根据这些数据对象创建画布。但是问题是我已经拥有的坐标适用于svg,而不适用于画布格式。
我需要找到一种方法来转换我具有的svg坐标列表,以便与画布坐标系相匹配或更像。
我愿意接受建议。
答案 0 :(得分:1)
您的问题不是很清楚,但是假设您有svg路径,则可以使用Path2D对象将其转换为画布路径:在下一个示例中,SVG路径为红色,画布路径为左黑色。
var svgPathApple = Apple.getAttribute("d");
var svgPathLeaf = Leaf.getAttribute("d");
var c = document.getElementById("c");
var ctx = c.getContext("2d");
var cw = c.width = 500;
var ch = c.height = 500;
var apple = new Path2D(svgPathApple);
var leaf = new Path2D(svgPathLeaf);
ctx.stroke(apple);
ctx.stroke(leaf);
canvas,svg{border:1px solid #d9d9d9; width:45vw;}
path{fill: none; stroke:red;}
<svg viewBox="0 0 500 500">
<path id="Apple" d="M376.349,171.58
c0,0-37.276,22.484-36.094,60.946s31.438,61.577,42.012,63.313c4.127,0.678-24.314,57.988-42.039,72.189
s-36.067,17.159-64.47,5.917c-28.403-11.242-48.521,0.724-65.089,6.871s-36.687-0.361-63.905-39.415
s-57.396-129.585-15.976-173.964s87.574-26.627,100-20.71s34.32,5.325,59.172-5.917S363.922,153.237,376.349,171.58z"/>
<path id="Leaf" d="M311.852,68.621c0,0,2.367,14.793-3.55,27.219
s-28.189,55.061-60.473,47.337c-0.809-0.193-5.529-14.482,1.398-29.002C259.004,93.682,284.49,70.699,311.852,68.621z"/>
</svg>
<canvas id="c"></canvas>
更新:
SVG代表可缩放矢量图形。尽管您的svg大小与画布大小相同,但实际上,您的svg大小是其四倍。为了知道实际大小,您必须查看viewBox
属性的值:“ 52 0 2104 1200”。转换为普通英语,您的svg宽度为2104,高度为1200。这还不是全部。您的svg坐标从x = 52且y = 0开始。给定SVG上的点p = {x:100,y:100},您的画布坐标为:x = (100 - 52)/2
和y = 100/2
;
接下来是一个简单的示例,其中我在画布上和svg元素上绘制了一个圆:
const canvas = document.getElementById("canv");
const ctx = canvas.getContext("2d");
let x = (100 - 52)/2,
y = 100/2,
r = 10/2;
ctx.beginPath();
ctx.arc(x,y,5,0,2*Math.PI);
ctx.fill();
canvas,svg{border:1px solid;}
<svg version="1.1" id="svgMap" width="1052px" height="600px" viewBox="52 0 2104 1200">
<circle id="testCircle" cx="100" cy ="100" r="10" />
</svg>
<canvas width="1052" height="600" id="canv"></canvas>
我希望这会有所帮助。