Skip to content

Instantly share code, notes, and snippets.

@ZJONSSON
Last active May 27, 2022 17:14
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save ZJONSSON/1254855 to your computer and use it in GitHub Desktop.
Save ZJONSSON/1254855 to your computer and use it in GitHub Desktop.
Simple transitioning slides with SVG and D3
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<script src="svg_slides.js"></script>
<script src="svg_interact.js"></script>
</head>
<body>
<script>
// There are probably better ways of loading the SVG, but this is one example I found
d3.xml("test.svg", "image/svg+xml", function(xml) {
d3.select("body").node().appendChild(xml.documentElement);
svg=d3.select("body").select("svg");
console.log(svg[0][0])
slides = svg_slides(svg,1500);
setTimeout(function() { svg_interact(svg);console.log("OK")},100);
// Lets test the slide scales - put a bouncing ball on slide id 3
s = slides[3];
circle = svg.append("svg:circle")
.attr("cx",s.scale_x(500)).attr("cy",s.scale_y(500))
.attr("r",20)
.style("fill","steelblue");
next = 500;
function bounce() {
next = -next;
circle.transition().duration(2500).attr("cx",s.scale_x(500+next))
.each("end",bounce);
}
bounce();
});
</script>
</body>
</html>
function svg_interact(svg,p) {
var p = p ? p : {},
zoom_speed = p.zoom_speed ? p.zoom_speed : 1.15,
viewBox = svg[0][0].viewBox.baseVal;
panning = null,
current_mouse = null;
/* Panning moves the viewbox */
function mousemove(){
current_mouse = d3.svg.mouse(this);
if (panning) {
viewBox.x +=(panning[0] -current_mouse[0]);
viewBox.y += (panning[1] - current_mouse[1]);
}
};
svg.on("mousemove",mousemove)
svg.on("mousedown", function() { panning = d3.svg.mouse(this)});
d3.select(window).on("mouseup",function () { panning = null;})
svg[0][0].ondragstart = function() { return false } // Firefox fix
/* Zoom with mousewheel - keeping mouse position in same location*/
function wheel(event) {
var delta = 0;
if (!event) event = window.event;
if (event.wheelDelta) {
delta = event.wheelDelta/120;
} else if (event.detail) {
delta = -event.detail/3;
}
move = (delta<0) ? -delta * zoom_speed : 1/(delta*zoom_speed);
viewBox.x=(current_mouse[0]-(current_mouse[0]-viewBox.x)*move);
viewBox.y=(current_mouse[1]-(current_mouse[1]-viewBox.y)*move);
viewBox.height = viewBox.height * move;
viewBox.width = viewBox.width * move;
};
svg[0][0].addEventListener('DOMMouseScroll', wheel, false);
svg[0][0].onmousewheel = wheel;
document.onmousewheel = function () { return null};
return svg;
}
/* This is a basic attempt to use d3 to process transitional slides from SVG files (i.e. Inkscape)
The main objective here was to keep everything as simple as possible
To create a slide, simply create a rectangle in inkscape where you set the object ID to "slide_" + a number
This number can be either integer or float, so "slide_1","slide_2" and "slide_3.56" all work.
The script sorts the slide-numbers and transitions between slides based on the final sorted order.
It is easy to add slides into a pre-existing ordering, simply by chosing a floating number in the middle of the two
Example: If we want to add slide between "slide_2" and "slide_3" we simply add a rectancle called "slide_2.5"
Keyboard definitions:
Right arrow: next slide
Left arrow: previous slide
Home: first slide
End: last slide
Please be aware that you need to remove any layer transition is the svg file (or put the layer transition to 0,0)
Each slide has a scale_x and scale_y functions that have pre-set range to the slide boundaries and a default
domain of [0,1000], allowing the user to position objects easily onto each slide.
ziggy.jonsson.nyc@gmail.com
*/
function svg_slides(svg,delay) {
var slides={},
slide = 0,
delay = delay ? delay : 3500;
svg.attr("preserveAspectRatio","xMidYid meet");
rects = svg.selectAll("rect")[0];
for (i=0;i<rects.length;i++) {
id = rects[i].id;
console.log(id);
if (id.slice(0,6)=='slide_') {
slides[id.slice(6)]=rects[i]
rects[i].scale_x = d3.scale.linear().range([rects[i].x.baseVal.value,rects[i].x.baseVal.value+rects[i].width.baseVal.value]).domain([0,1000]);
rects[i].scale_y = d3.scale.linear().range([rects[i].y.baseVal.value,rects[i].y.baseVal.value+rects[i].height.baseVal.value]).domain([0,1000]);
}
}
keys = Object.keys(slides).sort();
slides.keys = keys;
function next_slide() {
svg.transition().duration(delay).attr("viewBox",slides[keys[slide]].x.baseVal.value+" "+slides[keys[slide]].y.baseVal.value+" "+slides[keys[slide]].width.baseVal.value+" "+slides[keys[slide]].height.baseVal.value);
}
d3.select("body").on("touchmove", function() { if(slide<keys.length-1) {slide++; console.log(slide);}});
d3.select(window).on("keydown", function() {
switch (d3.event.keyCode) {
case 37: {if (slide>0) {slide=slide-1; console.log(slide);next_slide()};break}
case 39: {if(slide<keys.length-1) {slide++; console.log(slide);next_slide()};break}
case 36: {slide = 0;next_slide();break}
case 35: {slide = keys.length -1; next_slide();break}
}
});
// Start with the first slide
next_slide();
return slides
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@winniehell
Copy link

I love what you did there! 💖 This is just awesome! Thank you for sharing... 👍

@CrashLaker
Copy link

well... i'm just 10 years late.. awesome indeed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment