I used the following code to change the stroke-width when mouseover the path, but it doesn't work... I have checked many solutions on this matter, they seem to use the same solution as mine. My canvas is Raphael("svgContainer", 100, 100);
function drawPath(i,floorlevel,pointsNum){
var x1 = floorlevel[i].x;
var y1 = floorlevel[i].y;
var x2 = floorlevel[i+1].x;
var y2 = floorlevel[i+1].y;
var p = canvas.path("M"+x1 +" "+ y1);
p.attr("stroke", get_random_color());
p.attr("stroke-width",4);
p.attr("id",floorlevel[i].node+floorlevel[i+1].node);
p.animate({path:"M"+x1 +" "+ y1+ " L" + x2 +" "+ y2}, 1000);
var set = canvas.set();
var hoverIn = function() {
this.attr({"stroke-width": 10});
};
var hoverOut = function() {
this.attr({"stroke-width": 10});
}
p.hover(hoverIn, hoverOut, p, p);
set.push(p);
}
It seems to work fine when I sub in dummy values for the arguments you pass to the function:
http://jsfiddle.net/hKCDg/
I noticed you have the same stroke-width for hoverIn and hoverOut, which defeats the purpose.
var hoverIn = function() {
this.attr({"stroke-width": 10});
};
var hoverOut = function() {
this.attr({"stroke-width": 10});
};
I changed the latter to 5 in the demo here for visual effect.
Perhaps there's an error in the values you pass to the function?
Related
Am using raphael.js to render shapes to a canvas, but the problem is that there is a memory leak and the page crashes after some time. Can some one help me how it can be handled ? I am using underscore.js to handle the loop while removing still no luck. I tried changing the library to svg.js but the problem was worse. Thanks in advance, the code is as follows:
var paper = new Raphael(document.getElementById('visualizerContainer'), 545, 545);
paper.canvas.style.backgroundColor = '#000';
Raphael.fn.line = function(startX, startY, endX, endY){
return this.path('M' + startX + ' ' + startY + ' L' + endX + ' ' + endY);
};
var flag=0;
window.particleObject={
"id":"",
"obj":[]
}
function addParticles(){
if(flag) removeParticles(particleObject);
for(var i=0;i<5000;i++){
var x=Math.floor((Math.random() * 628) + 1);
var y=Math.floor((Math.random() * 571) + 1);
var circleName = "var circle"+i;
circleName = paper.circle(x, y, 1);
//var fillColor='#'+ ('000000' + (Math.random()*0xFFFFFF<<0).toString(16)).slice(-6);
circleName.attr("fill", "#0F0");
circleName.attr("stroke", "#ff");
particleObject.id=i;
particleObject.obj.push(circleName);
}
flag=1;
}
function removeParticles(particleObject){
_.map(particleObject.obj, function(o) {o.remove(); });
}
$.getJSON('assets/data/jp_Wall.json', function(data) {
$.each(data.features, function(id, obj) {
var wall = paper.line(obj.x1, obj.y1, obj.x2, obj.y2).attr({stroke:'red',fill:'red',"stroke-width": 3});
});
});
$.getJSON('assets/data/jp_ImpossibleSpace.json', function(data) {
$.each(data.features, function(id, obj) {
var width=(obj.x2-obj.x1);
var height=(obj.y2-obj.y1);
var top_left_x=obj.x1;
var top_left_y=obj.y1;
var rectangle = paper.rect(top_left_x, top_left_y, width, height).attr({stroke:'blue',"stroke-width": 3, "stroke-dasharray": "."});
});
});
addParticles();
setInterval(addParticles, 500);
Wall.json-->https://jsonblob.com/54f47ff7e4b0ae1ed0b1fcf2
jp_ImpossibleSpace.json-->https://jsonblob.com/54f48114e4b0ae1ed0b1fd04
It was my problem only. I forgot to clear my array of objects in window variable
I want to draw SVG path with mouse on canvas.
I don't want any library like rapheal.js here to draw shapes, I want pure JS.
I have creaed JS:
var svgCanvas = document.getElementById("svgCanvas");
var svgPath;
svgCanvas.addEventListener("touchstart", startDrawTouch, false);
svgCanvas.addEventListener("touchmove", continueDrawTouch, false);
svgCanvas.addEventListener("touchend", endDrawTouch, false);
function startDrawTouch(event)
{
var touch = event.changedTouches[0];
svgPath = createSvgElement("path");
svgPath.setAttribute("fill", "none");
svgPath.setAttribute("shape-rendering", "geometricPrecision");
svgPath.setAttribute("stroke-linejoin", "round");
svgPath.setAttribute("stroke", "#000000");
svgPath.setAttribute("d", "M" + touch.clientX + "," + touch.clientY);
svgCanvas.appendChild(svgPath);
}
function continueDrawTouch(event)
{
if (svgPath)
{
var touch = event.changedTouches[0];
var pathData = svgPath.getAttribute("d");
pathData = pathData + " L" + touch.clientX + "," + touch.clientY
svgPath.setAttribute("d", pathData);
}
}
function endDrawTouch(event)
{
if (svgPath)
{
var pathData = svgPath.getAttribute("d");
var touch = event.changedTouches[0];
pathData = pathData + " L" + touch.clientX + "," + touch.clientY
svgPath.setAttribute("d", pathData);
svgPath = null;
}
}
function createSvgElement(tagName)
{
return document.createElementNS("http://www.w3.org/2000/svg", tagName);
}
This take time on tablet to draw path. Having performance issue, in case you have better idea please share.
Thanks in advance.
You are reconstructing the path element in each continueDrawTouch call. That means converting it from the internal representation to a string then appending to the string and converting it back again.
Most browsers (Firefox for certain for instance) will be more performant if you avoid this and use the SVG DOM instead. The code would become:
if (svgPath)
{
var touch = event.changedTouches[0];
var newSegment = svgPath.createSVGPathSegLinetoAbs(touch.clientX, touch.clientY);
svgPath.pathSegList.appendItem(newSegment);
}
The same comment applies to the endDrawTouch function.
Maybe you can try if <polyline> and its .points property work and can give you better performance. Untested modification of your code:
var svgCanvas = document.getElementById("svgCanvas");
var svgPolyline;
svgCanvas.addEventListener("touchstart", startDrawTouch, false);
svgCanvas.addEventListener("touchmove", continueDrawTouch, false);
svgCanvas.addEventListener("touchend", endDrawTouch, false);
function startDrawTouch(event)
{
var touch = event.changedTouches[0];
svgPolyline = createSvgElement("polyline");
svgPolyline.setAttribute("fill", "none");
svgPolyline.setAttribute("shape-rendering", "geometricPrecision");
svgPolyline.setAttribute("stroke-linejoin", "round");
svgPolyline.setAttribute("stroke", "#000000");
svgCanvas.appendChild(svgPolyline);
continueDrawTouch(event);
}
function continueDrawTouch(event)
{
if (svgPolyline)
{
var touch = event.changedTouches[0];
var point = svgPolyline.ownerSVGElement.createSVGPoint();
point.x = touch.clientX;
point.y = touch.clientY;
var ctm = event.target.getScreenCTM();
if (ctm = ctm.inverse())
{
point = point.matrixTransform(ctm);
}
svgPolyline.points.appendItem(point);
}
}
function endDrawTouch(event)
{
continueDrawTouch(event);
svgPolyline = null;
}
function createSvgElement(tagName)
{
return document.createElementNS("http://www.w3.org/2000/svg", tagName);
}
Edit: .clientX/Y doesn't necessarily give you the coordinates you want, depending on the structure of your document, scroll or transformations. I therefore edited the code with some inspiration from another question (but using .screenX/Y, which should be more appropriate in connection with .getScreenCTM). The method name .getScreenCTM() caused me some confusion. .clientX/Y is indeed what's needed, see the specs.
<html>
<script type="text/javascript">
var name="name of troop/general"; var attack="attack"; var defense="defense"; var effect1=""; var effect2=""; var effect3=""; var effect4=""; var effect5=""; var effect6=""; var flavortext1=""; var flavortext2=""; var flavortext3=""; var flavortext4=""; var flavortext5=""; var flavortext6=""; var username="your name here"; var a="troop"; var b="common1"; var c="human"; var d="any"; var e="agility";
function setname()
{
name = document.forms["form"]["name"].value;
alert("unit name = " + name);
}
function setattack()
{
attack = document.forms["form"]["attack"].value;
alert("attack = " + attack);
}
function setdefense()
{
defense = document.forms["form"]["defense"].value;
alert("defense = " + defense);
}
function seteffect()
{
//using document.forms to get the value of effects
alert("effect = " + effect1 + effect2 + effect3 + effect4 + effect5 + effect6);
}
function setflavortext()
{
//using document.forms to get the value of flavortext
alert("flavortext =" + flavortext1 + flavortext2 + flavortext3 + flavortext4 + flavortext5 + flavortext6);
}
function setusername()
{
username = document.forms["form"]["username"].value;
alert("name = " + username);
}
function setimage()
{
base_image = new Image();
base_image.src = document.forms["form"]["image"].value;
base_image.onload = function
{
base.drawImage(base_image, 300, 30, 90, 90);
}
}
</script>
<canvas id="canvas" width="400" height="700" style="solid"></canvas>
<script type="text/javascript">
var mathmath = defense/4;
var attackvalue = attack + mathmath;
function writeall()
{
var can=document.getElementById("canvas");
var base=can.getContext("2d");
base.fillStyle="grey"; //background
base.fillRect(0,0,400,1200);
base.fillStyle="#FFBF00"; //orangeish
base.font="15px Arial";
base.fillText(name, 0, 20);
base.fillStyle="#EFFBF8" //white
base.fillText("Quality:", 0, 40); //this is the only base.fillText that works...
base.fillText(attack, 50, 80);
base.fillText(defense, 60, 100);
base.fillText(attackvalue, 120, 60);
//base.fillText's like the ones above, of varying colors
if(a == "general")
{
base.fillText(a, 350, 20);
}
//ifs like the one above
base.fillStyle="#FF4000" //dark orange
base.fillText(effect1, 0, 180);
//5 more effect vars being fillTexted; do not work...
var y = 0;
//ifs to set y
base.font="italic 15px Arial";
base.fillStyle="#EFFBF8" //white
//ifs to set y
base.font="15px Arial";
var x = 0;
//ifs to set x
base.fillText(username, 0, y+x);
if(c == "human")
{
base_image = new Image();
base_image.src = 'http://images2.wikia.nocookie.net/__cb20120812195219/dotd/images/c/c5/Race_human.png';
base_image.onload = function()
{
base.drawImage(base_image, 0, 105);
}
}
//ifs like the one above, a bunch of them; none work
</script>
</html>
I honestly have no idea where the problem is, but it is noteable it all worked as intended (which I will get into later) before I tried to add the setimage() function...
It is intended to create a large grey rectangle and write a bunch of stuff on it, I messed around a little so it might look weird; but right now all it makes is a grey rectancle with the word quality on it; and nothing happens when i press the button for the setimage() function, not even the alert I put in it... I've looked through it a couple times, then a couple times with notepad++ and I am confused...
Thanks for your time in advance.
I'm trying to change a position of a image that I have in HTML by using javascript. I can actually get it working if I have the following code:
function main()
{
var catOne = document.getElementById("cat1");
catOne.style.left = cat1.getX().toString() + "px";
catOne.style.top = cat1.getY().toString() + "px";
}
but when I change the code to this:
var catOne = new Cat("cat1", 300, 100);
function main()
{
catOne.setUp();
}
it doesn't work. and I dont know why, but it only gives me an error of "TypeError: Cannot read property 'style' of null"
This is my Cat class in javascript:
function Cat(id, x, y)
{
this.cat = document.getElementById(id);
this.x = x;
this.y = y;
}
Cat.prototype.setUp = function ()
{
this.cat.style.left = this.x.toString() + "px";
this.cat.style.top = this.y.toString() + "px";
};
Cat.prototype.getX = function ()
{
return this.x;
};
Cat.prototype.getY = function ()
{
return this.y;
};
TypeError: Cannot read property 'style' of null means your catOne does not exist in the DOM tree.
You should instantiate the Cat class when the DOM is ready (or on window load).
I don't know why you need that main() function but when does it execute? It should also execute when the DOM is ready.
var catOne;
function main() {
catOne.setUp();
}
window.onload = function() {
catOne = new Cat("cat1", 300, 100);
main();
}
I also suggest that you set the position of your cat to absolute if you are positioning it like that in your setUp() function. (I think you are already doing this with your CSS):
Cat.prototype.setUp = function ()
{
this.cat.style.position = 'absolute';
this.cat.style.left = this.x.toString() + "px";
this.cat.style.top = this.y.toString() + "px";
};
Here is the fiddle.
Other than that your code should work.
with:
var catOne = new Cat("cat1", 300, 100);
catOne.setUp();
works just fine.
I don't quite get it how You managed to get error You mentioned
link: http://jsfiddle.net/Z74mM/
have an object of a class Abon and then i want this object to move around the page.
a = new Abon();
a.init();
a.move();
the method move() contains:
function abon_move () {
var x = this.x;
var y = this.y;
var direction_x = Math.random()*5 - 5;
var direction_y = Math.random()*5 - 5;
var x_new = x + direction_x * this.movement_rate;
var y_new = y + direction_y * this.movement_rate;
console.log(x_new+" "+y_new)
$(".abonent."+this.id).animate( {
left:+x_new,
top:+y_new
}, 'slow', "linear", function() { this.move() });
}
All i want is that the method move (represented as function abon_move()) repeated again and again, after the animate stops. But the problem is that this.move() shown in callback has no connection to my object, because this in that place points to the HTML element, selected by jQuery.
UPD:
function Abon(id) {
...
this.move = abon_move;
...
}
Abon.prototype.move = abon_move;
And the actual method is the same, but with no callback in animate
then i try doing the following:
setInterval( a[0].move , 300); //doesn't work - says `this` members are undefined
setInterval( a[0].move() , 300); //works only one time and stops
Thank you for any help!
Try this :
function abon_move () {
var x = this.x;
var y = this.y;
var class = this;
...
}
Then, inside your jQuery animate, your can refer to your class using the variable class
Wrap the function abon_move() in a setTimeout call, as such: setTimeout(abon_move, 300); so it will run every 300 ms.