I'm trying to create an animated line as if its being drawn from one point to another. I have managed to get the line drawing on to the page but can't work out how to animate it as if it's being drawn?
https://jsfiddle.net/0sdt33dz/
function svgAnimate (){
var s = Snap('#svg');
var linePath = "M-3,148.6c0,0,43.9,7,49.4-17.2c3.5-15.3-9.4-19.7-17.3-13.8c-6,4.4-10,19,11.3,25.4 c24.9,7.5,70.7-31.2,91-61.8S233-41.5,286.3,29.2c0,0-60.7,35.5-24.9,87.9c36.2,53,83.5,15.6,83.5,15.6s19.3,19.5,68.4,17.1";
var lineLength = Snap.path.getTotalLength(linePath);
var lineDraw = s.path(linePath);
lineDraw.attr({
fill:'none',
stroke:'#009FE3',
'stroke-width' :6,
'stroke-linecap' :'round',
'stroke-linejoin' :'round',
'stroke-miterlimit' :10
});
lineDraw.animate({
stroke : '#fff'
},3000, mina.easein)
console.log(lineLength);
}
svgAnimate();
You're almost there, just missing two things.
First, you need to set the stroke-dasharray to '<length> <length>', this will create a "dashed" line with gaps/fill equal to the length of the entire line
lineDraw.attr({
fill:'none',
stroke:'#009FE3',
'stroke-dasharray': lineLength + ' ' + lineLength,
'stroke-dashoffset': lineLength,
'stroke-width' :6,
...
After this you need to animate the offset of the stroke to 0 using stoke-dashoffset
lineDraw.animate({
strokeDashoffset : 0
},3000, mina.easein)
working fiddle
var s = Snap("#myLine");
//Line parameters (x1, y1, x2, y2)
var line = s.line(30, 45, 30, 45);
line.attr({
stroke: "#000",
strokeWidth: 2
});
//Old x2 values is 30 and now it is increasing to 70 with 1 second duration
line.animate({x2: 70}, 1000);
I hope this answer will help you!
Related
im trying to put the marker-mid on the line element, im using SVG.js. For example im using this code:
var draw = SVG('yourdivid');
var line = draw.line( 100, 100, 0, 0).move(20, 20);
line.stroke({ color: '#000', width: 2};
now how can i put the marker at the mid of this line using the marker-mid?
i read the doc of svg.js and also this" https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/marker-mid#Examples"
they say that you can use the marker-mid element also with the line, i know that this marker works with the path element, but i need to use it with a line, can you help me please?
thank you for your help
You could just work out the mid point of the line yourself and draw a circle at that point.
var start = [100, 100];
var end = [0, 0];
function midPoint(start, end) {
return [
(start[0] + end[0]) / 2,
(start[1] + end[1]) / 2
];
}
var lineGroup = svg.group();
lineGroup.line(start[0][0], start[0][1], end[0][0], end[0][1]);
var dot = lineGroup.circle(3);
var mid = midPoint(start, end);
dot.cx(mid[0]);
dot.cy(mid[1]);
marker-mid does not work on lines. To have start and end markers, this code would do it:
var draw = SVG('yourdivid');
draw.line( 100, 100, 0, 0)
.move(20, 20)
.stroke({ color: '#000', width: 2})
.marker('start', 10, 10, function(add){
add.circle(10).center(5,5)
})
However, to have markers at the mid of a line see p0wdr.com's answer
I'm starting to learn SVG, and I came across a codepen that I wanted to modify - it originally had a triangle that went along the animated SVG path. I managed to remove the middle loop, and replace the triangle with an actual image. However, if you take a look at my pen (http://codepen.io/hybride/pen/pewzrO), you will see that the image does not actually smoothly/correctly goes along the animated path. How can I
get the image on the path,
have the image plane follow the path in that direction, as opposed to this weird squiggle thing the plane is now doing?
Thanks!
Also code provided:
HTML
<div id="svg-container">
<svg id="svgC" width="100%" height="100%" viewBox="0 0 820 220" preserveAspectRatio="xMidYMid meet"></svg>
CSS
#svg-container {
position:absolute;
z-index:99;
width: 90%;
margin: 0 auto;}
#svgC {padding: 20px;}
jQuery
// Pen JS Starts Here
jQuery(document).ready(function(){
// ---------
// SVG
var snapC = Snap("#svgC");
// SVG C - "Squiggly" Path
var myPathC = snapC.path("M62.9 14.9c-25-7.74-56.6 4.8-60.4 24.3-3.73 19.6 21.6 35 39.6 37.6 42.8 6.2 72.9-53.4 116-58.9 65-18.2 191 101 215 14.9c-25-7.74-56.6 14.9c-25-7.74-56.6 4.8-60.4").attr({
id: "squiggle",
fill: "none",
strokeWidth: "4",
stroke: "#ffffff",
strokeMiterLimit: "10",
strokeDasharray: "12 6",
strokeDashOffset: "180"
});
// SVG C - Triangle (As Polyline)
var Triangle = snapC.image("https://stage.livetext.com/wp-content/uploads/2017/02/Paper_Plane_Shadow.png", 0, 0, 150, 150);
initTriangle();
// Initialize Triangle on Path
function initTriangle(){
var triangleGroup = snapC.g( Triangle ); // Group polyline
movePoint = myPathC.getPointAtLength(length);
triangleGroup.transform( 't' + parseInt(movePoint.x - 15) + ',' + parseInt( movePoint.y - 15) + 'r' + (movePoint.alpha - 90));
}
// SVG C - Draw Path
var lenC = myPathC.getTotalLength();
// SVG C - Animate Path
function animateSVG() {
myPathC.attr({
stroke: '#fff',
strokeWidth: 4,
fill: 'none',
// Draw Path
"stroke-dasharray": "12 6",
"stroke-dashoffset": "180"
}).animate({"stroke-dashoffset": 10}, 4500,mina.easeinout);
var triangleGroup = snapC.g( Triangle ); // Group polyline
setTimeout( function() {
Snap.animate(0, lenC, function( value ) {
movePoint = myPathC.getPointAtLength( value );
triangleGroup.transform( 't' + parseInt(movePoint.x - 15) + ',' + parseInt( movePoint.y - 15) + 'r' + (movePoint.alpha - 90));
}, 4500,mina.easeinout, function(){
alertEnd();
});
});
}
// Animate Button
function kapow(){
$("#nin").click(function(event){
// Disable Button
$(this).attr('disabled','disabled');
// Animate Ball
if ($('#ball').hasClass('red')){
$('#ball').removeClass('red');
}
// Run SVG
animateSVG();
});
}
kapow();
});
The key is trying to align the center of the object to be animated with the start of the path, as it's probably not centered in the first place. The problem is with images and svgs it's hard to do this unless you have created the image yourself and have 0,0 as it's center. Otherwise you have to do some fiddling about.
You can do this by setting the x,y and rotation transform to get you going. Example..
snapC.image("https://stage.livetext.com/wp-content/uploads/2017/02/Paper_Plane_Shadow.png", -60, -60, 150, 150).transform('r270');
This will adjust the planes x,y by -60 and also rotate it, to get it aligned correct. It will probably need a bit of further tweaking finally as well.
example
I'm drawing an arrow between two spots on the page. Each time this is called, the arrow is cleared and redrawn with different points. Right now the line is drawing correctly, but there is no arrow at the end. I'm using the jQuery SVG plugin
var svg = $('#board').svg('get');
svg.clear();
var startX = fromCol*sideLen + sideLen/2;
var startY = fromRow*sideLen + sideLen/2;
var endX = toCol*sideLen + sideLen/2;
var endY = toRow*sideLen + sideLen/2;
svg.line(startX, startY, endX, endY, {
strokeWidth: 5
, stroke: 'yellow'
, strokeLineCap: 'round'
, strokeLineJoin: 'miter'
});
The camel-case variables are setting to the correct CSS properties, I double checked that. An example output of this code in the DOM is
`<line x1="375" y1="325" x2="325" y2="275" stroke-width="5" stroke="yellow" stroke-linecap="round" stroke-linejoin="miter"></line>`
I'm stumped. Thanks for the help!
Figured it out. I define this in the setup:
$('#board').svg();
var svg = $('#board').svg('get');
// Adds a marker to the svg defs element
var defs = svg.defs();
var marker = svg.marker(defs, 'arrow', 3, 2, 5, 5, 'auto');
// Define the shape of the marker
svg.polyline(marker, [[0,0], [4,2], [0,4], [1,2]], {
"fill" : "yellow"
});
And call this when drawing the line, similar to earlier but with the new setting and an id.
var svg = $('#board').svg('get');
var g = svg.group({stroke: 'yellow', strokeWidth: 5});
svg.line(g, startX, startY, endX, endY, {
"id" : "line"
, "strokeLineCap" : "round"
, "marker-end" : "url(#arrow)"
});
I am making a polygon from lines.
x = options.e.pageX - offset.left;
y = options.e.pageY - offset.top;
On click, I capture mouse position. After, I add that point to array of points.
roofPoints.push(new Point(x, y));
function Point(x, y) {
this.x = x;
this.y = y;
}
When all points are set I do this:
var roof = new fabric.Polyline(roofPoints, {
fill : 'purple',
});
The problem with this is that while I set points I am drawing lines for the polygon like so:
var points = [ x, y, x, y ];
lines.push(new fabric.Line(points, {
strokeWidth : 1,
selectable : false,
stroke : 'red'
}).setOriginX(x).setOriginY(y));
So basically I'm making a counter of a polygon and when I'm done drawing the counter, I just create a polygon. But the problem is that when I create polygon it doesn't fit in the counter it just moves away from the counter. I have tried to find how to correctly offset it.
roof.set({
left : left,
top : top,
});
I was trying to get left upper point of a bounding rectangle for the polygon and to set it so it places correctly. But that din't work. This how it looks
And a fiddle How it looks
Ok so I checked coords of created polygon and saw that it has recalculated them somehow and that's why it was offset. For example:
PointBefore
58 | 193
PointAfter
-189 | -52
This is how it changes, so to make the correct offset all I did was get it before I create the polygon and set top and left after it has been created.
var left = findLeftPaddingForRoof(roofPoints);
var top = findTopPaddingForRoof(roofPoints);
var roof = new fabric.Polyline(roofPoints, {
fill: 'purple'
});
roof.set({
left: left,
top: top
});
return roof;
And a fiddle that works.
This script doesn't work on 1.4.13 and 1.5.0 fabricjs versions. Cannot confirm on previus versions.
EDIT: Fixed the problem, also in later versions:
Change this:
var points = [ x, y, x, y ];
lines.push(new fabric.Line(points, {
strokeWidth : 1,
selectable : false,
stroke : 'red'
}).setOriginX(x).setOriginY(y));
into this:
var points = [ x, y, x, y ];
lines.push(new fabric.Line(points, {
strokeWidth : 1,
selectable : false,
stroke : 'red'
}));
Is there a way to position a rectangle in Raphael.js based on the center coordinates (much like positioning a circle)?
You can do it by simply creating your own custom element, here is an example on how it can be done :
Raphael.fn.MyRect = function( cx, cy, width, height ) {
var xLeftTop = cx - (width / 2);
var yLeftTop = cy - (height / 2);
this.rectObj = paper.rect( xLeftTop, yLeftTop, width, height );
return this;
};
var paper = Raphael(10, 50, 320, 200);
paper.MyRect( 95, 35, 50, 50 ); // 95 is the center in x and 35 the center in y
A live example : http://jsfiddle.net/7QMbH/
This way, you can create as many rectangle you want, and it makes your code understandable.
The easiest way is to create your rectangle with coordinates x - rect_width/2 and y - rect_heigth/2:
Example:
var rect_w = 180,
rect_h = 80;
var paper = Raphael(10, 10, 500, 500);
paper.rect(100 - rect_w/2, 100 - rect_h/2, rect_w, rect_h, 5);
// The last 5 gives curved edges to you rectangle (if you need it of course).
Basically, instead of 100,100 for top-left, you give 10,60. Good Luck