I am trying to create something with SVG that responds to mouse movement combined with random movement.
you can check the code here
https://jsfiddle.net/hass/Lfv2yjyf/
$(document).ready(function(){
var d = document;
var mysvg = d.getElementById("mysvg");
var mx,my,random,xmid,ymid,input;
setInterval(function() {
//svg size
var svgw = $("svg").width();
var svgh = $("svg").height();
//center point of svg
xmid = svgw/2;
ymid = svgh/2;
//random numbers
random = {
a: Math.floor(Math.random()*25),
b: Math.floor(Math.random()*25),
c: Math.floor(Math.random()*25)
};
//add event to svg
mysvg.addEventListener("mousemove", function(e) {
//aqcuire mouse position relative to svg
mx = e.clientX;
my = e.clientY;
//add <path> to svg
input = '<path d="M ' + xmid + ',' + ymid + ' l ' + 0 + ',' + 0 + ' ' + ((mx-xmid)/2) + ',' + random.a + ' ' + ((mx-xmid)-((mx-xmid)/2)) + ',' + ((my-ymid)-random.a) + ' ' + '" stroke="orange" stroke-width="7" stroke-linejoin="round" fill="none" />';
});
//display datas
$("#status1").html("X Position : " + mx + "<br>Y Position: " + my + "<br><br>Center Point X: " + xmid + "<br><br>Center Point Y: " + ymid + "<br><br>Width: " + svgw + "<br>Height: " + svgh + "<br><br>Random Value a: " + random.a + "<br>Random Value b: " + random.b + "<br>Random Value c: " + random.c);
$("#mysvg").html(input);
}, 10);
});
My problem here is the random movement of the line at midpoint only responds when I move the mouse, I know it doesn't work because the random value is only acquired with mouse movement.
what I'm trying to do is I want the random movement even without the mouse movement.
so I want to know how I acquire the values of global object in setInterval every 10 milliseconds or whatever value I set at "setInterval" function but I prefer almost every millisecond so I could get the random vibrating effect.
I also tried to write the "path" outside of mousemove function and it works and this is something I wanted to achieve
https://jsfiddle.net/hass/d2L4hda5/
but the problem here is when I check the console (browser's development tool → console tab) the values of the mouse x and mouse y is "NaN". but the rendering works.
I cannot figure out what I'm missing here.
so I want to get some advice if second link is what I want to achieve and get the right values of mouse x and mouse y or any other technique that works best.
Regards.
I'm not entirely sure what you problem is here. Is your problem that you can't seem to see the values iof mx and my in your browser tools? How are you trying to read them? Note that they aren't global variables. They are local to the ready() function. So, for instance, you won't be able to see the value if you simply type mx into the console.
Note also, that you don't need to keep adding the mousemove event handler every time your interval timer function gets called. It can be totally independent. See below.
$(document).ready(function(){
var d = document;
var mysvg = d.getElementById("mysvg");
var mx,my,random,xmid,ymid,input;
//svg size
var svgw = $("svg").width();
var svgh = $("svg").height();
//center point of svg
xmid = svgw/2;
ymid = svgh/2;
//add event to svg
mysvg.addEventListener("mousemove", function(e) {
//aqcuire mouse position relative to svg
mx = e.clientX;
my = e.clientY;
});
setInterval(function() {
//random numbers
random = {
a: Math.floor(Math.random()*25),
b: Math.floor(Math.random()*25),
c: Math.floor(Math.random()*25)
};
//add <path> to svg
input = '<path d="M ' + xmid + ',' + ymid + ' l ' + 0 + ',' + 0 + ' ' + ((mx-xmid)/2) + ',' + random.a + ' ' + ((mx-xmid)-((mx-xmid)/2)) + ',' + ((my-ymid)-random.a) + ' ' + '" stroke="orange" stroke-width="7" stroke-linejoin="round" fill="none" />';
//display datas
$("#status1").html("X Position : " + mx + "<br>Y Position: " + my + "<br><br>Center Point X: " + xmid + "<br><br>Center Point Y: " + ymid + "<br><br>Width: " + svgw + "<br>Height: " + svgh + "<br><br>Random Value a: " + random.a + "<br>Random Value b: " + random.b + "<br>Random Value c: " + random.c);
$("#mysvg").html(input);
}, 10);
});
html, body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
body {
overflow: hidden;
}
#wrapper {
width: 100%;
min-height: 100%;
margin: 0 auto;
position: relative;
}
svg {
position: absolute;
bottom: 0;
left: 0;
right: 0;
margin: 0 auto;
width: 100%;
height: 100%;
outline: 1px solid blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<p id="status1"></p>
<svg id="mysvg" width="300" height="300"></svg>
</div>
Related
var Belay = (function () {
var settings = {
strokeColor: '#fff',
strokeWidth: 2,
opacity: 1,
fill: 'none',
animate: true,
animationDirection: 'right',
animationDuration: .75
};
var me = {};
me.init = function (initObj) {
if (initObj) {
$.each(initObj, function (index, value) {
//TODO validation on settings
settings[index] = value;
});
}
}
me.set = function (prop, val) {
//TODO validate
settings[prop] = val;
}
me.on = function (el1, el2) {
var $el1 = $(el1);
var $el2 = $(el2);
if ($el1.length && $el2.length) {
var svgheight, p, svgleft, svgtop, svgwidth
var el1pos = $(el1).offset();
var el2pos = $(el2).offset();
var el1H = $(el1).outerHeight();
var el1W = $(el1).outerWidth();
var el2H = $(el2).outerHeight();
var el2W = $(el2).outerWidth();
var node1X = Math.round(el1pos.left + el1W);
var node2X = Math.round(el2pos.left);
var overlapping = node1X >= node2X;
var svgwidth = Math.abs(node2X - node1X);
var svgleft = Math.min(node1X, node2X);
var node1Y = Math.round(el1pos.top + el1H / 2);
var node2Y = Math.round(el2pos.top + el1H / 2);
var svgheight = Math.abs(node1Y - node2Y);
var svgtop = Math.min(node1Y, node2Y);
var pt1x = node1X - svgleft;
var pt1y = node1Y - svgtop + settings.strokeWidth;
var pt2x = node2X - svgleft;
var pt2y = node2Y - svgtop + settings.strokeWidth;
// cpt is the length of the control point vector
// variew with distance netween boxes
var cpt = Math.round(svgwidth * Math.min(svgheight / 300, 1));
if (overlapping) {
// Need to widen the svg because otherwise the bezier control
// points (and hence the curve) will extend outside it.
svgleft -= cpt;
svgwidth += 2 * cpt;
pt1x += cpt;
pt2x += cpt;
}
// Build the path decription
p = "M" + pt1x + "," + pt1y +
" L" + (pt1x + pt2x) / 8 + "," + pt1y +
" L" + (pt1x + pt2x) / 8 + "," + pt2y //+
" L" + (pt2x) / 1.03 + "," + pt2y +
" L" + (pt2x) / 1.03 + "," + (pt2y - 5) +
" L" + pt2x + "," + pt2y +
" L" + (pt2x) / 1.03 + "," + (pt2y + 5) +
" L" + (pt2x) / 1.03 + "," + pt2y;
//ugly one-liner
$ropebag = $('#ropebag').length ? $('#ropebag') : $('body').append($("<div id='ropebag' />")).find('#ropebag');
var svgnode = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
var defs = document.createElementNS('http://www.w3.org/2000/svg', "defs");
var marker = document.createElementNS('http://www.w3.org/2000/svg', "marker");
var path = document.createElementNS('http://www.w3.org/2000/svg', "path");
marker.setAttributeNS(null,"id","arrow");
marker.setAttributeNS(null,"markerWidth","13");
marker.setAttributeNS(null,"markerHeight","13");
marker.setAttributeNS(null,"refX","2");
marker.setAttributeNS(null,"refY","7");
marker.setAttributeNS(null,"markerUnits","userSpaceOnUse");
path.setAttributeNS(null,"d","M2,2 L2,13 L8,7 L2,2");
marker.appendChild(path);
defs.appendChild(marker);
var newpath = document.createElementNS('http://www.w3.org/2000/svg', "path");
newpath.setAttributeNS(null, "d", p);
newpath.setAttributeNS(null, "stroke", settings.strokeColor);
newpath.setAttributeNS(null, "stroke-width", settings.strokeWidth);
newpath.setAttributeNS(null, "opacity", settings.opacity);
newpath.setAttributeNS(null, "fill", settings.fill);
newpath.setAttributeNS(null, "marker-end", "url(#arrow)");
svgnode.appendChild(newpath);
svgnode.appendChild(defs);
$(svgnode).css({
left: svgleft,
top: svgtop - settings.strokeWidth,
position: 'absolute',
width: svgwidth,
height: svgheight + settings.strokeWidth * 2,
minHeight: '20px',
'pointer-events': 'none'
});
$ropebag.append(svgnode);
if (settings.animate) {
// THANKS to http://jakearchibald.com/2013/animated-line-drawing-svg/
var pl = newpath.getTotalLength();
// Set up the starting positions
newpath.style.strokeDasharray = pl + ' ' + pl;
if (settings.animationDirection == 'right') {
newpath.style.strokeDashoffset = pl;
} else {
newpath.style.strokeDashoffset = -pl;
}
// Trigger a layout so styles are calculated & the browser
// picks up the starting position before animating
// WON'T WORK IN IE. If you want that, use requestAnimationFrame to update instead of CSS animation
newpath.getBoundingClientRect();
newpath.style.transition = newpath.style.WebkitTransition = 'stroke-dashoffset ' + settings.animationDuration + 's ease-in-out';
// Go!
newpath.style.strokeDashoffset = '0';
}
}
}
me.off = function () {
$("#ropebag").empty();
}
return me;
}());
/*********************** Custom JavaScript **********************************/
$(document).ready(function () {
$(".draggable").draggable({
drag: function (event, ui) {
Belay.off();
drawConnectors();
}
});
function drawConnectors() {
$(".parent").each(function () {
var theID = this.id;
$("." + theID).each(function (i, e) {
var rand = Math.random() * .7 + .3;
Belay.set('animationDuration', rand)
Belay.on($("#" + theID), e)
});
})
}
$(window).resize(function () {
Belay.off();
drawConnectors();
});
Belay.init({
strokeWidth: 1
});
Belay.set('strokeColor', '#999');
drawConnectors();
});
.row{
margin-top:2in;
}
.box{
border:1px solid #ccc;
padding:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<body>
<div class="row">
<div class="col-md-4">
<div class="pull-left ">
<div class="parent draggable box" id="parent1">Left drag</div>
</div>
<div class="pull-right">
<div class="child parent1 draggable box">Right drag</div>
</div>
</div>
</div>
</body>
Hi as per this example how-to-change-the-lines-between-two-points-from-curved-to-straight-lines-with-on how to draw arrow at the end of the path dynamically
can someone tell me what is wrong in adding marker end in my code
var Belay = (function ()
{
var settings = {
strokeColor: 'red',
strokeWidth: 2,
opacity: 1,
fill: 'none',
animate: true,
animationDirection: 'right',
animationDuration: .75
};
var me = {};
me.init = function (initObj) {
if (initObj) {
$.each(initObj, function (index, value) {
//TODO validation on settings
settings[index] = value;
});
}
}
me.set = function (prop, val) {
//TODO validate
settings[prop] = val;
}
me.on = function (el1, el2) {
var $el1 = $(el1);
var $el2 = $(el2);
if ($el1.length && $el2.length) {
var svgheight, p, svgleft, svgtop, svgwidth
var el1pos = $(el1).offset();
var el2pos = $(el2).offset();
var el1H = $(el1).outerHeight();
var el1W = $(el1).outerWidth();
var el2H = $(el2).outerHeight();
var el2W = $(el2).outerWidth();
var node1X = Math.round(el1pos.left + el1W);
var node2X = Math.round(el2pos.left);
var overlapping = node1X >= node2X;
var svgwidth = Math.abs(node2X - node1X);
var svgleft = Math.min(node1X, node2X);
var node1Y = Math.round(el1pos.top + el1H / 2);
var node2Y = Math.round(el2pos.top + el1H / 2);
var svgheight = Math.abs(node1Y - node2Y);
var svgtop = Math.min(node1Y, node2Y);
var pt1x = node1X - svgleft;
var pt1y = node1Y - svgtop + settings.strokeWidth;
var pt2x = node2X - svgleft;
var pt2y = node2Y - svgtop + settings.strokeWidth;
// cpt is the length of the control point vector
// variew with distance netween boxes
var cpt = Math.round(svgwidth * Math.min(svgheight / 300, 1));
if (overlapping) {
// Need to widen the svg because otherwise the bezier control
// points (and hence the curve) will extend outside it.
svgleft -= cpt;
svgwidth += 2 * cpt;
pt1x += cpt;
pt2x += cpt;
}
p = "M" + pt1x + "," + pt1y +
" L" + (pt1x + pt2x) / 8 + "," + pt1y +
" L" + (pt1x + pt2x) / 8 + "," + pt2y +
" L" + (pt2x) / 1.03 + "," + pt2y +
" L" + (pt2x) / 1.03 + "," + (pt2y - 5) +
" L" + pt2x + "," + pt2y +
" L" + (pt2x) / 1.03 + "," + (pt2y + 5) +
" L" + (pt2x) / 1.03 + "," + pt2y;
//ugly one-liner
$ropebag = $('#ropebag').length ? $('#ropebag') : $('body').append($("<div id='ropebag' />")).find('#ropebag');
var svgnode = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
//try
var defs = document.createElementNS('http://www.w3.org/2000/svg', "defs");
var marker = document.createElementNS('http://www.w3.org/2000/svg', "marker");
var path = document.createElementNS('http://www.w3.org/2000/svg', "path");
marker.setAttributeNS(null,"id","arrow");
marker.setAttributeNS(null,"markerWidth",10);
marker.setAttributeNS(null,"markerHeight",10);
marker.setAttributeNS(null,"refX",0);
marker.setAttributeNS(null,"refY",5);
marker.setAttributeNS(null,"viewbox","0 0 10 10");
marker.setAttributeNS(null,"orient","auto");
marker.setAttributeNS(null,"markerUnits","strokeWidth");
path.setAttributeNS(null,"d","M 0 0 L 10 5 L 0 10");
////try
marker.appendChild(path);
defs.appendChild(marker);
var newpath = document.createElementNS('http://www.w3.org/2000/svg', "path");
newpath.setAttributeNS(null, "d", p);
newpath.setAttributeNS(null, "stroke", settings.strokeColor);
newpath.setAttributeNS(null, "stroke-width", settings.strokeWidth);
newpath.setAttributeNS(null, "opacity", settings.opacity);
newpath.setAttributeNS(null, "fill", settings.fill);
newpath.setAttributeNS(null, "marker-end", "url(#arrow)");
newpath.appendChild(defs);
svgnode.appendChild(newpath);
//for some reason, adding a min-height to the svg div makes the lines appear more correctly.
$(svgnode).css({
left: svgleft,
top: svgtop - settings.strokeWidth,
position: 'absolute',
width: svgwidth,
height: svgheight + settings.strokeWidth * 2,
minHeight: '20px',
'pointer-events': 'none'
});
$ropebag.append(svgnode);
if (settings.animate) {
// THANKS to http://jakearchibald.com/2013/animated-line-drawing-svg/
var pl = newpath.getTotalLength();
// Set up the starting positions
newpath.style.strokeDasharray = pl + ' ' + pl;
if (settings.animationDirection == 'right') {
newpath.style.strokeDashoffset = pl;
} else {
newpath.style.strokeDashoffset = -pl;
}
// Trigger a layout so styles are calculated & the browser
// picks up the starting position before animating
// WON'T WORK IN IE. If you want that, use requestAnimationFrame to update instead of CSS animation
newpath.getBoundingClientRect();
newpath.style.transition = newpath.style.WebkitTransition = 'stroke-dashoffset ' + settings.animationDuration + 's ease-in-out';
// Go!
newpath.style.strokeDashoffset = '0';
}
}
}
me.off = function ()
{
$("#ropebag").empty();
}
return me;
} ());
function drawConnectors()
{
}
You don't seem to be appending newpath to anything.
Also you are appending defs to newpath. I'm not sure that works (I've never tried it). You should probably avoid doing that. Append the defs to the SVG instead.
I'm trying to move a div left/down by pressing buttons. It causes an unexpected change from position:relative to position:static. An explanation of why this occurs would be great.
<html>
<body style='border: solid blue 1px; height: 90px'>
<div style='width:900px; height: 80px; position:relative; border: solid green 1px'>
<div id='test' style='position:relative; left:500px; top:0px; border: solid red 2px; width:300px'>
<button id='L' onclick='theButton(this)'>move left</button>
<button id='R' onclick='theButton(this)'>reset</button>
<button id='T' onclick='theButton(this)'>move down</button>
</div>
</div>
<script>
function theButton(x) {
console.log("x: " + x);
var aDiv = document.getElementById('test');
var topPosition = window.getComputedStyle(aDiv).top;
console.log(topPosition);
var topPositionDigitString = topPosition.slice(0,topPosition.length-2); // this strips "px" from the string
var topPositionNumber = parseInt(topPositionDigitString); // this converts to the numeric we need
//var leftPosition = window.getComputedStyle(aDiv).left;
var leftPosition = aDiv.style.left;
console.log( leftPosition);
var leftPositionDigitString = leftPosition.slice(0,leftPosition.length-2);
var leftPositionNumber = parseInt(leftPositionDigitString);
console.log("leftPositionNumber: " + leftPositionNumber);
if(x.id=='L') {
leftPositionNumber += 50;
console.log("leftPositionNumber: " + leftPositionNumber);
var setleftPosition = 'left:' + leftPositionNumber + 'px';
aDiv.style = setleftPosition;
console.log("getComputedStyle(aDiv).left: " + window.getComputedStyle(aDiv).left);
console.log("aDiv.style.left: " + aDiv.style.left);
}
if(x.id=='R') {
aDiv.style = 'left:0px';
}
if(x.id=='T') {
topPositionNumber += 50;
var setTopPosition = 'top:' + topPositionNumber + 'px';
aDiv.style = setTopPosition;
}
console.log("x: " + x);
console.log("topPosition:" + topPosition);
console.log("getComputedStyle(aDiv).left: " + window.getComputedStyle(aDiv).left);
console.log("getComputedStyle(aDiv).position: " + window.getComputedStyle(aDiv).position);
}
</script>
</body>
</html>
I've put the code on
JSBin https://jsbin.com/vineqeedit?html,js,console,output
in case that's more convenient for anyone who wants to use that.
Thanks for any help,
Gerard
Fixed:
function theButton(x) {
console.log("x: " + x);
var aDiv = document.getElementById('test');
var topPosition = window.getComputedStyle(aDiv).top;
console.log(topPosition);
var topPositionDigitString = topPosition.slice(0, topPosition.length - 2); // this strips "px" from the string
var topPositionNumber = parseInt(topPositionDigitString); // this converts to the numeric we need
//var leftPosition = window.getComputedStyle(aDiv).left;
var leftPosition = aDiv.style.left;
console.log(leftPosition);
var leftPositionDigitString = leftPosition.slice(0, leftPosition.length - 2);
var leftPositionNumber = parseInt(leftPositionDigitString);
console.log("leftPositionNumber: " + leftPositionNumber);
if (x.id == 'L') {
leftPositionNumber -= 50;
console.log("leftPositionNumber: " + leftPositionNumber);
var setleftPosition = leftPositionNumber + 'px';
aDiv.style.left = setleftPosition;
console.log("getComputedStyle(aDiv).left: " + window.getComputedStyle(aDiv).left);
console.log("aDiv.style.left: " + aDiv.style.left);
}
if (x.id == 'R') {
aDiv.style.left = '500px';
aDiv.style.top = '0px';
}
if (x.id == 'T') {
topPositionNumber += 50;
var setTopPosition = topPositionNumber + 'px';
aDiv.style.top = setTopPosition;
}
console.log("x: " + x);
console.log("topPosition:" + topPosition);
console.log("getComputedStyle(aDiv).left: " + window.getComputedStyle(aDiv).left);
console.log("getComputedStyle(aDiv).position: " + window.getComputedStyle(aDiv).position);
}
<body style='border: solid blue 1px; height: 90px'>
<div style='width:900px; height: 80px; position:relative; border: solid green 1px'>
<div id='test' style='position:relative; left:500px; top:0px; border: solid red 2px; width:300px'>
<button id='L' onclick='theButton(this)'>move left</button>
<button id='R' onclick='theButton(this)'>reset</button>
<button id='T' onclick='theButton(this)'>move down</button>
</div>
</div>
<script></script>
</body>
Anyway your trouble is because position: relative; is set in the element's inline style. And inside your code you had several places where you set the entire element.style = "string", which replaced the whole inline css with one single style online. So I changed it to just change either left or top with element.style.left = newLeft, and that fixes it.
This is the troublesome code find coordinates of the middle of a square svg
The code snippet below doesn't work here. You might want to use another editor or check the lin above for easy access.
$(function() {
var ss = {
"y": 40,
"x": 4,
"n": 3, // Speed
"xD": 0,
"yD": 0,
"rotation": 0,
/*"cx":, This is where I want my coords to change
"cy":,*/
};
var move;
var bbox = document.getElementById("block_green").getBBox();
var ctm = document.getElementById("block_green").getCTM()
var cx = bbox.x + bbox.width/2;
var cy = bbox.y + bbox.height/2;
var pt = document.getElementById("svg").createSVGPoint();
pt.x = cx;
pt.y = cy;
pt = pt.matrixTransform(ctm);
setInterval(move, .01);
setInterval(alert(pt.x + ", " pt.y), 20000);
function move() {
ss.x = ss.x + (ss.xD * ss.n);
ss.y = ss.y + (ss.yD * ss.n);
$("#block_green").attr({
y: ss.y,
x: ss.x
}).css({
"-webkit-transform" : "rotate("+ ss.rotation +"deg)",
"-moz-transform": "rotate(" + ss.rotation + "deg)",
"-ms-transform": "rotate(" + ss.rotation + "deg)",
"transform": "rotate(" + ss.rotation + "deg)"
});
}
$(document).keydown(function(e) {
ss.rotation = e.which == 37 ? ss.rotation -2 : ss.rotation;
ss.rotation = e.which == 39 ? ss.rotation +2 : ss.rotation
ss.yD = e.which == 38 ? -1 : ss.yD;
ss.yD = e.which == 40 ? 1 : ss.yD;
ss.xD = e.which == 69 ? 1 : ss.xD;
ss.xD = e.which == 81 ? -1 : ss.xD;
e.preventDefault();
}).keyup(function(e) {
ss.yD = e.which == 38 ? 0 : ss.yD;
ss.yD = e.which == 40 ? 0 : ss.yD;
ss.xD = e.which == 69 ? 0 : ss.xD;
ss.xD = e.which == 81 ? 0 : ss.xD;
e.preventDefault();
});
});
body {
margin: 0;
overflow: hidden;
}
svg {
background-color: black;
width: 100vw;
height: 100vh;
z-index: 1;
}
#block_green {
fill: black;
stroke: #00ff00;
stroke-width: .5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg id="svg">
<rect x="4" y="4" width="80" height="60" id="block_green"/>
</svg>
This code should alert every 20 seconds, the coordinates of the square. In order to get the coordinates of the center of the square, I've tryied this question:
How to get Mid point of <g> tag in svg using javascript
If you are using codepen, you'll find the proble in lines 9-16 & 18.
First of all, there is a syntax error in your code which will prevent its execution:
setInterval(alert(pt.x + ", " pt.y), 20000);
needs to be
setInterval(alert(pt.x + ", " + pt.y), 20000);
But that's not the major point here. The way you are trying to set up your interval will not work as expected. It will not repeatedly call alert() but instead evaluate the expression alert(pt.x + ", " + pt.y) once when you call setInterval(). For this reason you will see one initial alert popup printing the starting values for pt. The expression will eventually evaluate to undefined which will be taken as the first argument to setInterval(), i.e. the function to call repeatedly is referred to as undefined, which obviously is not what you intended in the first place.
You need to wrap the calculations of the rect's center in a function if you want to have it alert the updated values on repeated calls. You are then able to pass the reference to a function, not to undefined to setInterval(). Check my JSFiddle for the way it might work for you:
function getCenter() {
var bbox = document.getElementById("block_green").getBBox();
var ctm = document.getElementById("block_green").getCTM()
var cx = bbox.x + bbox.width/2;
var cy = bbox.y + bbox.height/2;
var pt = document.getElementById("svg").createSVGPoint();
pt.x = cx;
pt.y = cy;
return pt.matrixTransform(ctm);
}
setInterval(function() {
var pt = getCenter();
alert(pt.x + ", " + pt.y);
}, 20000);
You can do that by applying the transformation of the element to its center. This way is a general approach to obtain absolute coordinates from a local space. The idea is: Compute the center of the rectangle in local coordinates, by using the attribute values directly. Afterwards one applies the transformation of the svg element to that point.
var svg = document.getElementById('root'),
rect = document.getElementById('block_green'),
x = rect.x.baseVal.value,
y = rect.x.baseVal.value,
w = rect.width.baseVal.value,
h = rect.height.baseVal.value,
c = svg.createSVGPoint(),
mtr = rect.getTransformToElement(svg);
c.x = x + w/2;
c.y = y + h/2;
c = c.matrixTransform(mtr);
FIDDLE
so I am trying to check if I already added the a div with the same id and if I did, I chage its color to red. But for some reason my divs have a length of 0 and the if clause is never true.
I've been doing some research and this is very often due to a float, but I don't have one. I am just positionting my divs absolutely and appending them to the body.
Please have a look, any help I will be grateful for!
Thanks.
<body>
<style>
#box {
background: url('a.gif') no-repeat;
width: 50px;
height: 30px;
position: absolute;
top:210px;
left: 0;
}
#grid {
background: url('grid.gif') no-repeat;
width: 423px;
height: 240px;
margin-left: 4px;
}
#stand {
background: black;
width: 4px;
height: 240px;
margin-left: 23px;
}
#hstand {
/*horizontal stand for the carrier*/
width: 423px;
margin-left: 27px;
height: 4px;
background: black;
}
</style>
<script>
$(function() {
$('#box').click(function(e) {
var i = 0;
while (i < 50) { //specifying the cycles for the box' movement
var hstandWidth = $("#hstand").width() + 27; //getting the current x-coordinates
//array to randomly select x-coordinates from
var items = Array(hstandWidth - (50) * 1, hstandWidth - (50) * 2, hstandWidth - (50) * 3, hstandWidth - (50) * 4, hstandWidth - (50) * 5, hstandWidth - (50) * 6, hstandWidth - (50) * 7, hstandWidth - (50) * 8);
//variable with the x-coordinates, which are randomly fetched from the array
var moveLeft = items[Math.floor(Math.random() * items.length)];
//array to randomly select y-coordinates from
var items2 = Array(30, 30 * 2, 30 * 3, 30 * 4, 30 * 5, 30 * 6, 30 * 7);
//variable with the y-coordinates, which are randomly fetched from the array
var moveTop = items2[Math.floor(Math.random() * items2.length)];
// y-achs movement
$(this).animate({
"top": "" + moveTop + "px"
}, 80);
// x-achs movement with the callback function which should add the colored div to every position the box has been
// create closure to capture moveTop and moveLeft values for later callback
// use different named variables xmoveTop and xmoveLeft to distinguish the
// closure variable from the outer for loop variable
(function(obj, xmoveTop, xmoveLeft) {
$(obj).animate({
"left": "" + xmoveLeft + "px"
}, 80, function() {
if ($("#" + xmoveLeft + xmoveTop + "").length > 0) {
$("#" + xmoveLeft + xmoveTop + "").css("background", "red");
} else {
$("<div style='position: absolute; top: " + xmoveTop + "px; left: " + xmoveLeft + "px; background: blue; width: 50px; height: 30px;' id='" + xmoveTop + xmoveLeft + "'></div>").appendTo("body");
console.log($("#" + xmoveLeft + xmoveTop + "").length);
}
});
})(this, moveTop, moveLeft);
//get the box to the initial position
$(this).animate({
"left": "0px"
}, 80);
$(this).animate({
"top": "210px"
}, 80);
//mark cycle passed
i++;
}
});
});
</script>
</head>
<body>
<div id="box"></div>
<div id="stand">
<div id="grid"></div>
</div>
<div id="hstand"></div>
</body>
You create your div with id="xmoveTop + xmoveLeft" but you search for it with id="xmoveLeft + xmoveTop".
So change this line :
if ($("#" + xmoveLeft + xmoveTop + "").length > 0) {
$("#" + xmoveLeft + xmoveTop + "").css("background", "red");
To :
if ($("#" + xmoveTop + xmoveLeft + "").length > 0) {
$("#" + xmoveTop + xmoveLeft + "").css("background", "red");
You search for
"#"+xmoveLeft + xmoveTop +""
but you create the id with
" id='"+ xmoveTop + xmoveLeft +"'"
Since they are created as strings you do not use the sum but concatenated strings..
Wrap them in parenthesis, so you get the actual sum ..
"#"+ (xmoveLeft + xmoveTop) +"" and id='"+ (xmoveTop + xmoveLeft) +"'
i have a JavaScript project (using jquery), inside it i draw a canvas by code and then i insert array of images on it. it represents fine without any error.
problem: later on, i try to get these images inside from canvas to compare if they have the same src or the same id to don't replace it with the new image
my functions are:
var inter;
var screen;
function onClick(id){
getScreen(id, function(data){
screen=window.open('',id,'width=' + data.maxX + ',height=' + data.maxY , true);
if (screen.document.getElementById("screen") != null ){
screen.document.getElementById("screen").innerHTML = "";
}
screen.document.write('<div id="screen"><canvas id="screenCanvas" width=' +
data.maxX + ' height=' + data.maxY +
' style="border:2px solid #000000;color:#000000;" ></canvas></div>');
draw(data);
inter = setInterval(function(){screen(id); }, 5000);
});
}
function screen(id){
getScreen(id, function(data){
if (screen.closed == true){
clearInterval(inter);
return;
}
if((screen.document.getElementById('screenCanvas').width != data.maxX) ||
(data.maxY != screen.document.getElementById('screenCanvas').height)){
screen.close();
screen=window.open('',id,'width=' + data.maxX + ',height=' + data.maxY , true);
screen=window.open('',id,'width=' + data.maxX + ',height=' + data.maxY , true);
if (screen.document.getElementById("screen") != null ){
screen.document.getElementById("screen").innerHTML = "";
}
screen.document.write('<div id="screen"><canvas id="screenCanvas" width=' +
data.maxX + ' height=' + data.maxY +
' style="border:2px solid #000000;color:#000000;" ></canvas></div>');
draw(data);
});
}
function draw(data) {
var canvas = screen.document.getElementById('screenCanvas');
var context = canvas.getContext('2d');
var tileY = 0;
var tileX = 0;
var counter = 0;
var tileWidth = data.tileWidth;
var tileHeight = data.tileHeight;
for (var i=0;i<(data.maxX/data.tileWidth);i++){
for (var j=0;j<(data.maxY/data.tileHeight);j++){
var img = new Image();
img.onload = (function(img, tileX, tileY, tileWidth, tileHeight){
return function() {
context.drawImage(img,tileX, tileY, tileWidth, tileHeight);
}
})(img, tileX, tileY, tileWidth, tileHeight);
img.src = "http://myserver:8080/images/screen/tile/" +
data.tiles[counter].imageId;
tileX = tileX + parseInt(data.tileWidth);
counter ++;
}
tileY = tileY + parseInt(data.tileHeight);
tileX = 0;
}
}
</script>
this code gets an array (data) that contains list of (id, maxX, maxY, tileWidth, tileHeight, tiles[x, y, imageId]) and open new window, then write in this window the canvas code and draw images then calls a timer to work each 5 seconds. after each 5 seconds, screen method calls to re-get the data again and check if screen open then it remove all inner html to rewrite new canvas, and it tests if sizes changes.
this code works fine without any error, but i need to edit these code to get images inside canvas and test it they has the same imageId, don't download it again.(i don't save image id, to get images by, we can store it in img.id, or get images by src since, imageId is a part of image path that makes it unique).
Note:
id[unique](is the id of the user),
maxX(maximum width of the screen),
maxY(maximum height of the screen),
tileWidth(width of each image),
tileHeight(height of each image),
tiles(list of images)
x(left position of the image)
y(top postion of the image)
imageId[unique](id of each image)
example: data[id:1,maxX:1920,maxY:1080,tileWidth:480,tileHeight:270,tiles:(x:2,y:1,imageId:1a)]
any help?
as Ravi Jain said you can't get the image drawn to canvas object, and as robertc said you can use img element.
try these functions that specify the usage of img element not canvas:
function onClick(id){
getScreen(id, function(data){
var inter;
var screen;
var width = parseInt(data.maxX) + parseInt(data.tileWidth);
var height = parseInt(data.maxY) + parseInt(data.tileHeight);
screen=window.open('',id,'width=' + width + ',height=' + height , true);
draw(screen, data);
inter = setInterval(function(){screen(screen, inter, id); }, 5000);
});
}
function screen(screen, inter, id){
getScreen(id, function(data){
if (screen.closed == true){
clearInterval(inter);
return;
}
if((screen.document.getElementById("screen").style.width != data.maxX + "px") ||
(screen.document.getElementById("screen").style.height != data.maxY + "px")){
screen.close();
var width = parseInt(data.maxX) + parseInt(data.tileWidth);
var height = parseInt(data.maxY) + parseInt(data.tileHeight);
screen=window.open('',id,'width=' + width + ',height=' + height , true);
}
draw(screen, data);
});
}
function draw(screen, data) {
var screenDiv = screen.document.getElementById("screen");
if (screenDiv == null) screen.document.write('<div id="screen" style="width:' +
data.maxX + '; height:' + data.maxY + '; " style="margin: 0 auto;" >');
var tileY = 0;
var tileX = 0;
var counter = 0;
for (var i=0;i<(data.maxX/data.tileWidth);i++){
for (var j=0;j<(data.maxY/data.tileHeight);j++){
var imageSource = screen.document.getElementById("id_" + counter);
var path = "http://myserver:8080/images/screen/tile/" +
data.tiles[counter].imageId;
if (imageSource == null){
screen.document.write('<img id="id_' + counter + '" src="' + path +
'" height="' + data.tileHeight + '" width="' + data.tileWidth + '" />');
}else if(imageSource.src != path){
imageSource.src = path;
}
tileX = tileX + parseInt(data.tileWidth);
counter ++;
}
tileY = tileY + parseInt(data.tileHeight);
tileX = 0;
}
if (screenDiv == null) screen.document.write('</div>');
}
</script>
your code are working fine that's true, but for one instance only, you declare var screen and var inter at the top of the script not in the function, this means that if you click on the first user to get it's screen (as what i understood of your code, what your project did), the timer of the first user stops and of the second user starts. this code that i wrote solve this problem and your problem to replace the source of the image if it changes.
hope this help you man,
GOOD LUCK;
Once you've drawn something on canvas it's pixels. It doesn't retain the object that was used to create those pixels. If you want this sort of information then you either need to maintain it yourself outside of canvas, or use something which retains objects for you like SVG.