将d3 svg坐标转换为画布坐标,或尝试将两者的相同位置匹配

时间:2018-09-26 00:52:59

标签: javascript d3.js svg canvas coordinates

我有一些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坐标列表,以便与画布坐标系相匹配或更像。

我愿意接受建议。

1 个答案:

答案 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)/2y = 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> 

我希望这会有所帮助。