首页 > 解决方案 > 使用 SVG 和 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!

这是一个小提琴:

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>

Edit2: 我尝试使用 JQuery 的:

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

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

但完全相同的事情发生了:(

有趣的是,当我改用e.clientXe.clientX时,它会更好,但又不行:(

标签: javascriptsvgpaint

解决方案


你好,我又解决了!我使用了 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);
 
}

这是一个小提琴:

http://jsfiddle.net/zsaeLokh/

提示:

“d3.mouse”不再适用于新版本的 D3。使用 V5.9.2 或更低版本。如果你使用它,它会给出一个错误:

d3.mouse 不是函数

在这里读到我们可以使用“d3.pointer(event)”来代替。

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

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

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

未捕获的 ReferenceError:未定义 d3

最后,在

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

您应该记住将div更改为元素的名称。例如,如果它是一个span,请像这样更改它:

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

谢谢,希望你可以使用它,再见。

笔记:

我没有写完整的代码,我用了这个小提琴。


推荐阅读