I tried to make something like paint of Windows, with SVG and JS. It works well, but it has a bug. I can not describe that how is that. You should see it. But it seems when you're drawing a line, it jumps to another position! Can anyone help me please?
Here is the Code:
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");
}
}
}
})
Edit:
I think the problem is "e.target.getBoundingClientRect"; Cause I've set the SVG's width to 300. But when the line had jumped, I looked for "rect.width" and saw that's 20! While it had to be 300!
Here is a Fiddle:
https://jsfiddle.net/qrL2mvea/1
And here is the full code on 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: I tried to use JQuery's:
"event.pageX - $(this).offset().left;"
and "event.pageY - $(this).offset().top;",
but exactly the same happens :(
The funny part is that when I use e.clientX and e.clientX instead, it's better, but again it's not Ok :(
H i again, I solved it! I used D3 (Version 5.9.2 in jsfiddle, and 5 from it's origirnal website).
Here is the new code:
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);
}
And here is a fiddle:
Tips:
"d3.mouse" doesn't work in new versions of D3 anymore. Use V5.9.2 or less. If you use it, It'll give an error:
d3.mouse is not a function
I read Here that we can use "d3.pointer(event)" instead.
You can add Version 5 of that by adding this code to your html code:
<script src="https://d3js.org/d3.v5.min.js"></script>
You can add it Wherever you want. But remember to add the JS part After the div. Otherwise, it'll give you an error:
Uncaught ReferenceError: d3 is not defined
And at last, in
var vis = d3.select("div").append("svg")
You should remember to change the div, to the element's name. For Example, if it's a span, change it like this:
var vis = d3.select("span").append("svg")
Thanks, hope you can use it, Bye.
Note:
I didn't write the full code, I used this fiddle.