Last active
May 27, 2022 17:14
-
-
Save ZJONSSON/1254855 to your computer and use it in GitHub Desktop.
Simple transitioning slides with SVG and D3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 | |
} |
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
I love what you did there! 💖 This is just awesome! Thank you for sharing... 👍