Animating a continuous line horiizontally and vertically [closed] - d3.js

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm attempting to animate (transition) the “drawing” of an SVG path/line. The specific line I want to draw would be go 300px to the right, then continue 100px down, then 200px to the left. But it would be one single, continuous line with no curves or breaks.
Currently I can make it work by building the lines individually and applying a transition. Start at X1,Y1/X2,Y2--transition to new X2, Y2--for this duration, with this delay, and repeat, and repeat, and repeat.
Is there an easier way to do this? For example using a single SVG element rather than 3 and populate the X/Y coordinates from an array, for instance?
Any specific examples or pointing me in a general direction would be appreciated.
Thanks

This is entirely possible, though it's a little quirky to get the effect you want. It involves setting a very large stroke-dash-array (actually the entire length of your path) and then setting the dash-offset (also to the length of your shape). You set this up to the point that none of the line is originally visible, and alter the dash-offset such that the line comes into view.
There's a really good article on CSS Tricks SVG Line Animation that explains the principle. I wrote a little helper to do this for me in D3 that looks like this:
d3.selectAll(".draw")
.style("stroke-dasharray", function () { return this.getTotalLength(); })
.style("stroke-dashoffset", function () { return this.getTotalLength(); })
.transition()
.duration(3000)
.style("stroke-dashoffset", 0);
.draw {
fill: #232a29;
stroke: #232a29;
stroke-width: 2px;
fill-rule:nonzero;
fill-opacity:0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="500" height="500">
<g>
<g transform="translate(0,600)scale(1,-1)">
<!-- Circle -->
<path class="draw circle" d="m 97.44,308.52 c 0,90.53 73.42,163.92 163.98,163.92 90.56,0 163.98,-73.39 163.98,-163.92 0,-90.53 -73.42,-163.92 -163.98,-163.92 -90.56,0 -163.98,73.39 -163.98,163.92 z" />
</g>
</g>
</svg>

Related

Plotly.js, show tooltips outside of chart container

I need to implement a plotly.js chart on a page with a very restricted width. As a result, a tooltip is partially cut. Is it possible to cause tooltip not to be limited by plotly.js container size?
My code example at codepen: https://codepen.io/anatoly314/pen/gOavXzZ?editors=1111
//my single trace defined as following but it's better to see example at codepen
const yValue1 = [1000];
const trace1 = {
x: [1],
y: yValue1,
name: `Model 1`,
text: yValue1.map(value => Math.abs(value)),
type: 'bar',
textposition: 'outside'
};
It is, by design, not possible for any part of the chart to overflow its container.
I would say it is wrong to say that by design this is not possible! It is a bit hacky, but when you add the following lines, it shows the label outside of svg:
svg.main-svg,svg.main-svg *
{
overflow:visible !important;
}
The answer given by rokdd works. However the css selector should be more specific, otherwise it's natural that you will introduce subtle bugs (particularly if you need to scroll the content where the plotly chart is contained).
If we look at the DOM tree constructed by Plotly, we find that the tooltips are created inside the <g class="hoverlayer"></g> element (which is a direct child of one of the three <svg class="main-svg"></svg>). So that parent (that svg.main-svg element) is only one that needs to affected.
The ideal css selector in this case would be the :has selector. However it's still not supported (as of 2022): https://css-tricks.com/the-css-has-selector/
So the next simplest thing is to use a little bit of javascript right after we call Plotly.newPlot:
// get the correct svg element
var mainSvgEl = document.querySelector('#positive g.hoverlayer').parentElement;
mainSvgEl.style['overflow'] = 'visible';
Or in a more generic way (works for any chart):
Array.from(document.querySelectorAll('g.hoverlayer')).forEach(hoverEl => {
let mainSvgEl = hoverEl.parentElement;
mainSvgEl.style['overflow'] = 'visible';
});

Dashed line path following the moving images in D3

Here i'm working on moving images dynamically with random x and y, inside a zooming & dragging SVG. Now I want to append dashed path following these moving images. Similar to the image below:
I found a D3 example, where a dotted path following the mouse. I tried the same code to create a path for one image for the time being. Instead of mouse X & Y coordinates, i used the random X and Y values of moving image.
var pt = [];
pt.push(randomX);pt.push(randomY);
tick(pt);
function tick(pt) {
// push a new data point onto the back
ptdata.push(pt);
// Redraw the path:
path.attr("d", function(d) { return line(d);})
// If more than 100 points, drop the old data pt off the front
if (ptdata.length > npoints) {
ptdata.shift();
}
}
But the result was thick lines displayed in a disorder manner on top of the background image (Grass Texture image). Please check out the FIDDLE and please suggest a way to create dashed line path for the moving images.
First problem: "result was thick lines displayed"
Reason you need to give fill none
.line {
fill: none;
stroke: #000;
stroke-width: 1.5px;
stroke-dasharray: 2,5;
}
You had not given the style for the line.
Second problem: disorder manner on top of the background image
The reason is you running the time interval in a span of 50 millisecond,
but transition to move the image from point 1 to point 2 is 6000 millisecond thus the images are not able to move to its new calculated random position.
In short the anomaly is because you creating new points in 50 milliseconds but want to transition into the new place in 6000 milliseconds, so the points are not able to move to its position.
I have corrected the time interval to create points to 1 second.
Also i have changed the transition time of image to move in 100 milliseconds.
Working code here

How to not interrupt a mouseover d3 transition on mouseout?

I have a piece of code that moves a line on mouseover like this:
some_svg
.on("mouseover", function() {
my_line.transition().attr("transform", function(d) {
return "translate(" + [d.new_x, d.new_y] + ")";
});
})
However let's say the transition takes a whole second to complete (I believe this is the d3 default), if I were to move the mouse over some_svg then quickly move the mouse out before one second, then the line stops as soon as I move the mouse out and it will be partly done with the transition. In other word, the line will be in some position between the old and new position.
How do I make sure the transition will always complete no matter if I move the mouse out (as long as I don't move it back to another some_svg)?
The default duration (if you don't set one) is 250ms.
The simpler way to do not interrupt a mouseover transition is not setting a mouseout behaviour that changes the transition. As long as you don't move to an element that has an mouseover/mousemove event handler that interferes with the ongoing transition, the transition will complete. That being said, I cannot understand or reproduce your statement ("the line stops as soon as I move the mouse out and it will be partly done with the transition").
This is easy to confirm: hover over the rectangle below. It will complete it's transition regardless you move the mouse out of it.
d3.select("rect").on("mouseover", function(){
d3.select(this).transition().duration(5000).attr("transform", "translate(350, 0)");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="400" height="200">
<rect x="0" y="50" width="40" height="20" fill="teal"></rect>
</svg>

SVG with 10.000+ nodes - fast in IE and Safari, slow in Chrome and Firefox

I'm facing a problem that I thought would have been easier to solve than it actually is.
I want to create a puzzle with 4860 pieces for a game. The mesh of the puzzle is made with SVG. Below I'm reporting part of the code, just to give you an idea. The code is working as you can see in the last link I gave you.
I created in defs a list of paths (18 in total), then a long list of 4860 so that I can make my puzzle.
When the mouse moves over one piece, I want this piece to be highlighted.
That's the code (first part), followed by a series of tags like the one in the example.
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" width="1200" height="1200" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" xml:space="preserve">
<defs>
<style type="text/css">
.use1 {
stroke: #000000;
fill: #ffffff;
fill-opacity: 0.1;
stroke-linecap: butt;
}
.use1:hover {
fill: #ffffff;
fill-opacity: 0.8;
stroke: #3273BE;
stroke-width: 10;
}
.base {
}
</style>
<path id="a0" d="m152.199493 121.414993c-0.349991 2.4 -0.3 4.8 0 7.169998c1.200012 8.3 6.6 15.9 16.3 17.419998c12.858994 2 14 -5.5 23.2 . (...) "/>
.... the other 17 paths .....
</defs>
<image x="0" y="0" width="1200" height="720" xlink:href="lana-del-rey-ultraviolence-recensione.jpg" />
<use xlink:href="#C5" x="-50" y="-50" transform="scale(0.088) rotate(0)" class="use1" id="1"/>
....
... x 4860 ....
....
</svg>
You can see the result here:
http://www.ridiesorridi.it/puzzle/17.svg
If you open it in Safari or IE it works PERFECTLY with no lag. If you open in Chrome or Firefox to highlight a piece it's extremely slow. You can imagine when I put this SVG inside an HTML page ... !! Instead in IE and Safari it keeps working great.
My question is: how can I solve this problem with Chrome and Firefox?
I've already tried to remove extra decimals (to "optimize svg") but it didn't work.
Edit I noticed that in Chrome and Firefox, if I zoom in (like 400%) it works PERFECTLY. Once it has all the elements together, it keeps having problems (compared to IE and Safari)
Reducing accuracy would only help parsing speed. Once the SVG was parsed, it shouldn't make a difference.
I am not sure what, if any, optimisations FF and Chrome use when testing hover for SVG elements. But I would certainly try reducing the complexity of the pieces. For instance, the piece "g1" has 89 path commands in its definition. You should be able to reduce that by 4x, at least, and still get an accurate jigsaw piece shape.

Are there any online tools to test SVG paths?

I'm building an application that uses SVG paths, and I'd like to be able to see my paths rendered. Is there a site, say something like JSFiddle, on which you can paste in an SVG path, get it validated, and see it rendered?
EDIT: I've found that JSFiddle works fairly well for this, by selecting Raphael.js, svg.js, etc as a framework. e.g. http://jsfiddle.net/DFhUF/1393/
var paper = Raphael(0, 0, 300, 500);
paper.path("M75,75 m-50,0 a50,50 0 1,0 100,0 a50,50 0 1,0 -100,0")
.attr({stroke: "#808", opacity: 1, "stroke-width" : 6})
paper.path("M75,225 m-40,-50 h80, a10,10 0 0,1 10,10 v80 a10,10 0 0,1 -10,10 h-80 a10,10 0 0,1 -10,-10 v-80 a10,10 0 0,1 10,-10")
.attr({stroke: "#808", opacity: 1, "stroke-width" : 6})
That's probably good enough for my needs, but it would be nice to know if there are other tools to help test and debug editing of SVG Paths.
If you just want to quickly try out some SVG in your browser and not mess around with saving and loading files, jsFiddle is a great option.
Just use the following code as a template:
<svg xmlns="http://www.w3.org/2000/svg">
<path d="your path data here"></path>
</svg>
I created a sample to work from here.
jsFiddle also supports frameworks such as D3, PaperJs and Raphael from a dropdown on the left-hand side.
A few places to test and tweak live:
http://vectorpaint.yaks.co.nz/
http://editor.method.ac/
https://github.com/SVG-Edit/svgedit
http://scriptdraw.com is no longer maintained.
You can use my helper web-page
http://naiksoftware.github.io/svg.html
Edit: your update didn't show for some reason before I posted this ...
Paste your SVG path into a text file with a .svg name, and open it in a browser.
Alternatively, create a small page like this
<html>
<head><title>My SVG test page</title></head>
<body>
<h1>My SVG test</h1>
<object id="SVG" type="image/svg+xml" data="MySvgTest.svg"
width="1000" height="1500"/>
</body>
</html>
and open it in a browser (see the Primer). It assumes your SVG is in MySvgTest.svg

Resources