使用 SVG 和 JS 制作类似绘画的东西

Make something like paint with SVG and JS

我尝试使用 SVG 和 JS 制作类似 Windows 的绘画。它运行良好,但有一个错误。我无法描述那是怎么回事。你应该看到它。但是当你画一条线时,它似乎跳到另一个位置!谁能帮帮我?

这是代码:

Html:

<div id="Test" >
<svg height="300" width="300"></svg>
</div>

JavaScript:

var i=0;
var Sx;
var Sy;
var Show = false;
document.addEventListener('DOMContentLoaded', function(event) {
document.getElementById('Test').onmousedown = function clickEvent(e) {
      var rect = e.target.getBoundingClientRect();
      Sx = e.clientX - rect.left; //x position within the element.
      Sy = e.clientY - rect.top;  //y position within the element.
      Show = true;
      
}
document.getElementById('Test').onmouseup = function clickEvent2(e) {
      rect = e.target.getBoundingClientRect();
      var Ex = e.clientX - rect.left; //x position within the element.
      var Ey = e.clientY - rect.top;  //y position within the element.
      var TheLine = document.createElementNS("http://www.w3.org/2000/svg","line");
      TheLine.innerHTML = "";
      document.getElementsByTagName("svg")[0].appendChild(TheLine);
      i++;
      var LineZ = document.getElementsByTagName("line")[i];
      Show = false;
}
document.getElementById('Test').onmouseleave = function clickEvent4(e) {
    Show = false;
    console.log(":(");
    i++;
}
document.getElementById('Test').onmousemove = function clickEvent3(e) {
    if (Show == true)
    {
        rect = e.target.getBoundingClientRect();
        Ex = e.clientX - rect.left; //x position within the element.
        Ey = e.clientY - rect.top;
        
        var TheLine = document.createElementNS("http://www.w3.org/2000/svg","line");
      document.getElementsByTagName("svg")[0].appendChild(TheLine);
      ///i++;
      ///console.log(Sx," ",Sy," ", Ex, " ", Ey);
      var LineZ = document.getElementsByTagName("line")[i];
      if (LineZ != undefined && Ex != 0 && Ey != 0 && Ex != 1 && Ey != 1){
      document.getElementsByTagName("line")[i].setAttributeNS(null,"x1", Sx);
      document.getElementsByTagName("line")[i].setAttributeNS(null,"y1", Sy);
      document.getElementsByTagName("line")[i].setAttributeNS(null,"x2", Ex);
      document.getElementsByTagName("line")[i].setAttributeNS(null,"y2", Ey);
      document.getElementsByTagName("line")[i].setAttribute("style","stroke:rgb(255,0,0);stroke-width:2;visibility:visible");
      }
    }
}
})

编辑:

我认为问题是“e.target.getBoundingClientRect”;因为我已将 SVG 的宽度设置为 300。但是当该行跳转时,我查找“rect.width”并看到它是 20!虽然它必须是 300!

这是一个Fiddle:

https://jsfiddle.net/qrL2mvea/1

这里是 snippest 上的完整代码:

var i=0;
var Sx;
var Sy;
var Show = false;
document.addEventListener('DOMContentLoaded', function(event) {
document.getElementById('Test').onmousedown = function clickEvent(e) {
      var rect = e.target.getBoundingClientRect();
      Sx = e.clientX - rect.left; //x position within the element.
      Sy = e.clientY - rect.top;  //y position within the element.
      Show = true;
      
}
document.getElementById('Test').onmouseup = function clickEvent2(e) {
      rect = e.target.getBoundingClientRect();
      var Ex = e.clientX - rect.left; //x position within the element.
      var Ey = e.clientY - rect.top;  //y position within the element.
      var TheLine = document.createElementNS("http://www.w3.org/2000/svg","line");
      TheLine.innerHTML = "";
      document.getElementsByTagName("svg")[0].appendChild(TheLine);
      i++;
      var LineZ = document.getElementsByTagName("line")[i];
      Show = false;
}
document.getElementById('Test').onmouseleave = function clickEvent4(e) {
    Show = false;
    console.log(":(");
    i++;
}
document.getElementById('Test').onmousemove = function clickEvent3(e) {
    if (Show == true)
    {
        rect = e.target.getBoundingClientRect();
        Ex = e.clientX - rect.left; //x position within the element.
        Ey = e.clientY - rect.top;
        
        var TheLine = document.createElementNS("http://www.w3.org/2000/svg","line");
      document.getElementsByTagName("svg")[0].appendChild(TheLine);
      ///i++;
      ///console.log(Sx," ",Sy," ", Ex, " ", Ey);
      var LineZ = document.getElementsByTagName("line")[i];
      if (LineZ != undefined && Ex != 0 && Ey != 0 && Ex != 1 && Ey != 1){
      document.getElementsByTagName("line")[i].setAttributeNS(null,"x1", Sx);
      document.getElementsByTagName("line")[i].setAttributeNS(null,"y1", Sy);
      document.getElementsByTagName("line")[i].setAttributeNS(null,"x2", Ex);
      document.getElementsByTagName("line")[i].setAttributeNS(null,"y2", Ey);
      document.getElementsByTagName("line")[i].setAttribute("style","stroke:rgb(255,0,0);stroke-width:2;visibility:visible");
      }
    }
}
})
body
{
    margin: 0px;
}
#Test
{
    border:2px dotted blue;
    width:300px;
    height:300px;
    background-color:lightblue;
    position: fixed;
    top: 10%;
  }
<div id="Test" >
<svg height="300" width="300"></svg>
</div>

编辑2: 我尝试使用 JQuery 的:

"event.pageX - $(this).offset().left;"

和“event.pageY - $(this).offset().top;”,

但情况完全一样:(

有趣的是,当我使用 e.clientXe.clientX 时,效果更好,但是又不行了:(

你好,我解决了!我使用了 D3(jsfiddle 中的版本 5.9.2,以及来自其原始网站的 5)。

这是新代码:

Html:

<div id="Test" >

CSS:

body
{
    margin: 0px;
}
#Test
{
    border:2px dotted blue;
    width:300px;
    height:300px;
    background-color:lightblue;
    position: fixed;
    top: 100px;
    left: 100px;
}
svg {
    border: 1px solid grey;
}

line {
    stroke: steelblue;
    stroke-width: 2px;
    stroke-linecap: round;
}

JavaScript:

var line;

var vis = d3.select("div").append("svg") 
    .attr("width", 300)
    .attr("height", 300)
    .on("mousedown", mousedown)
    .on("mouseleave", mouseleave)
    .on("mouseup", mouseup);

function mousedown() {
    var m = d3.mouse(this);
    line = vis.append("line")
        .attr("x1", m[0])
        .attr("y1", m[1])
        .attr("x2", m[0])
        .attr("y2", m[1]);
    
    vis.on("mousemove", mousemove);
}

function mousemove() {
    var m = d3.mouse(this);
    line.attr("x2", m[0])
        .attr("y2", m[1]);
}

function mouseup() {
    vis.on("mousemove", null);
}
function mouseleave() {

 vis.on("mousemove", null);
 
}

这里是 fiddle:

http://jsfiddle.net/zsaeLokh/

提示:

"d3.mouse" 不再适用于新版本的 D3。使用 V5.9.2 或更低版本。如果你使用它,它会报错:

d3.mouse is not a function

我读到 Here 我们可以使用 "d3.pointer(event)" 代替。

您可以通过将此代码添加到您的 html 代码来添加版本 5:

<script src="https://d3js.org/d3.v5.min.js"></script>

你可以把它添加到任何你想要的地方。但是记得在之后加上div的JS部分。否则,它会给你一个错误:

Uncaught ReferenceError: d3 is not defined

最后,在

var vis = d3.select("div").append("svg") 

您应该记得将 div 更改为元素的名称。例如,如果它是 span,请将其更改为:

var vis = d3.select("span").append("svg") 

谢谢,希望你能用上,再见。

注:

我没有写完整的代码,我用了this fiddle.