├── .gitignore ├── src ├── main.js ├── data.json ├── index.html └── Viz.svelte ├── rollup.config.ssr.js ├── rollup.config.js ├── README.md ├── package.json ├── index.html └── bundle.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Viz from './Viz.svelte'; 2 | import data from './data.json'; 3 | 4 | document.body.innerHTML = ''; 5 | 6 | new Viz({ 7 | target: document.body, 8 | props: { 9 | segments: data 10 | } 11 | }); -------------------------------------------------------------------------------- /src/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "size": 5, 4 | "label": "this thing", 5 | "color": "rgb(100,180,200)" 6 | }, 7 | { 8 | "size": 8, 9 | "label": "that thing", 10 | "color": "rgb(150,200,250)" 11 | }, 12 | { 13 | "size": 11, 14 | "label": "another thing", 15 | "color": "rgb(80,100,150)" 16 | } 17 | ] -------------------------------------------------------------------------------- /rollup.config.ssr.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import json from 'rollup-plugin-json'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | export default { 6 | input: 'src/Viz.svelte', 7 | output: { 8 | file: 'build/Viz-ssr.js', 9 | format: 'cjs' 10 | }, 11 | plugins: [ 12 | resolve(), 13 | json(), 14 | svelte({ generate: 'ssr' }) 15 | ] 16 | }; -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import json from 'rollup-plugin-json'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | import { terser } from 'rollup-plugin-terser'; 5 | 6 | export default { 7 | input: 'src/main.js', 8 | output: { 9 | file: 'bundle.js', 10 | format: 'iife', 11 | }, 12 | plugins: [ 13 | resolve(), 14 | json(), 15 | svelte({ css: false }), 16 | terser() 17 | ] 18 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svelte-d3-arc-demo 2 | 3 | https://svelte-d3-arc-demo.surge.sh 4 | 5 | This simple demo shows Svelte and d3-shape working together. The visualisation is prebaked on each deploy, but there's also an interactive JavaScript version (drag the slider, pointlessly). 6 | 7 | Made in response to [this tweet](https://twitter.com/cramforce/status/839521783552294914) — Svelte is as general-purpose as they come, and this app's JavaScript weighs less than 5kb. (Not sure about GPU-optimised...) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "rollup": "^1.11.0", 4 | "rollup-plugin-json": "^4.0.0", 5 | "rollup-plugin-node-resolve": "^4.2.3", 6 | "rollup-plugin-svelte": "^5.0.3", 7 | "rollup-plugin-terser": "^4.0.4", 8 | "svelte": "^3.1.0" 9 | }, 10 | "dependencies": { 11 | "d3-shape": "^1.3.5" 12 | }, 13 | "scripts": { 14 | "build": "npm run build:client && npm run build:ssr && node build", 15 | "build:client": "rollup -c rollup.config.js", 16 | "build:ssr": "rollup -c rollup.config.ssr.js", 17 | "deploy": "surge . svelte-d3-arc-demo.surge.sh", 18 | "predeploy": "npm run build" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Viz.svelte: -------------------------------------------------------------------------------- 1 | 31 | 32 | 56 | 57 | 58 | 59 | {#each arcs as arc} 60 | 61 | 62 | 63 | 64 | {arc.label} 65 | {arc.label} 66 | {/each} 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | this thing 24 | this thing 25 | 26 | 27 | 28 | that thing 29 | that thing 30 | 31 | 32 | 33 | another thing 34 | another thing 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /bundle.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";function t(){}function n(t){return t()}function e(){return Object.create(null)}function i(t){t.forEach(n)}function r(t){return"function"==typeof t}function o(t,n){return t!=t?n==n:t!==n||t&&"object"==typeof t||"function"==typeof t}function c(t,n){t.appendChild(n)}function a(t,n,e){t.insertBefore(n,e)}function s(t){t.parentNode.removeChild(t)}function h(t){return document.createElementNS("http://www.w3.org/2000/svg",t)}function u(t){return document.createTextNode(t)}function l(t,n,e,i){return t.addEventListener(n,e,i),()=>t.removeEventListener(n,e,i)}function f(t,n,e){null==e?t.removeAttribute(n):t.setAttribute(n,e)}function _(t,n){n=""+n,t.data!==n&&(t.data=n)}let y;function x(t){y=t}const p=[],d=Promise.resolve();let g=!1;const v=[],b=[],m=[];function $(t){b.push(t)}function M(){const t=new Set;do{for(;p.length;){const t=p.shift();x(t),T(t.$$)}for(;v.length;)v.shift()();for(;b.length;){const n=b.pop();t.has(n)||(n(),t.add(n))}}while(p.length);for(;m.length;)m.pop()();g=!1}function T(t){t.fragment&&(t.update(t.dirty),i(t.before_render),t.fragment.p(t.dirty,t.ctx),t.dirty=null,t.after_render.forEach($))}function w(t,n){t.$$.dirty||(p.push(t),g||(g=!0,d.then(M)),t.$$.dirty={}),t.$$.dirty[n]=!0}function A(o,c,a,s,h,u){const l=y;x(o);const f=c.props||{},_=o.$$={fragment:null,ctx:null,props:u,update:t,not_equal:h,bound:e(),on_mount:[],on_destroy:[],before_render:[],after_render:[],context:new Map(l?l.$$.context:[]),callbacks:e(),dirty:null};let p=!1;var d;_.ctx=a?a(o,f,(t,n)=>{_.ctx&&h(_.ctx[t],_.ctx[t]=n)&&(_.bound[t]&&_.bound[t](n),p&&w(o,t))}):f,_.update(),p=!0,i(_.before_render),_.fragment=s(_.ctx),c.target&&(c.hydrate?_.fragment.l((d=c.target,Array.from(d.childNodes))):_.fragment.c(),c.intro&&o.$$.fragment.i&&o.$$.fragment.i(),function(t,e,o){const{fragment:c,on_mount:a,on_destroy:s,after_render:h}=t.$$;c.m(e,o),$(()=>{const e=a.map(n).filter(r);s?s.push(...e):i(e),t.$$.on_mount=[]}),h.forEach($)}(o,c.target,c.anchor),M()),x(l)}class z{$destroy(){var n,e;e=!0,(n=this).$$&&(i(n.$$.on_destroy),n.$$.fragment.d(e),n.$$.on_destroy=n.$$.fragment=null,n.$$.ctx={}),this.$destroy=t}$on(t,n){const e=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return e.push(n),()=>{const t=e.indexOf(n);-1!==t&&e.splice(t,1)}}$set(){}}var E=Math.PI,N=2*E,P=N-1e-6;function C(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function R(){return new C}function k(t){return function(){return t}}C.prototype=R.prototype={constructor:C,moveTo:function(t,n){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)},closePath:function(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,n){this._+="L"+(this._x1=+t)+","+(this._y1=+n)},quadraticCurveTo:function(t,n,e,i){this._+="Q"+ +t+","+ +n+","+(this._x1=+e)+","+(this._y1=+i)},bezierCurveTo:function(t,n,e,i,r,o){this._+="C"+ +t+","+ +n+","+ +e+","+ +i+","+(this._x1=+r)+","+(this._y1=+o)},arcTo:function(t,n,e,i,r){t=+t,n=+n,e=+e,i=+i,r=+r;var o=this._x1,c=this._y1,a=e-t,s=i-n,h=o-t,u=c-n,l=h*h+u*u;if(r<0)throw new Error("negative radius: "+r);if(null===this._x1)this._+="M"+(this._x1=t)+","+(this._y1=n);else if(l>1e-6)if(Math.abs(u*a-s*h)>1e-6&&r){var f=e-o,_=i-c,y=a*a+s*s,x=f*f+_*_,p=Math.sqrt(y),d=Math.sqrt(l),g=r*Math.tan((E-Math.acos((y+l-x)/(2*p*d)))/2),v=g/d,b=g/p;Math.abs(v-1)>1e-6&&(this._+="L"+(t+v*h)+","+(n+v*u)),this._+="A"+r+","+r+",0,0,"+ +(u*f>h*_)+","+(this._x1=t+b*a)+","+(this._y1=n+b*s)}else this._+="L"+(this._x1=t)+","+(this._y1=n);else;},arc:function(t,n,e,i,r,o){t=+t,n=+n;var c=(e=+e)*Math.cos(i),a=e*Math.sin(i),s=t+c,h=n+a,u=1^o,l=o?i-r:r-i;if(e<0)throw new Error("negative radius: "+e);null===this._x1?this._+="M"+s+","+h:(Math.abs(this._x1-s)>1e-6||Math.abs(this._y1-h)>1e-6)&&(this._+="L"+s+","+h),e&&(l<0&&(l=l%N+N),l>P?this._+="A"+e+","+e+",0,1,"+u+","+(t-c)+","+(n-a)+"A"+e+","+e+",0,1,"+u+","+(this._x1=s)+","+(this._y1=h):l>1e-6&&(this._+="A"+e+","+e+",0,"+ +(l>=E)+","+u+","+(this._x1=t+e*Math.cos(r))+","+(this._y1=n+e*Math.sin(r))))},rect:function(t,n,e,i){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)+"h"+ +e+"v"+ +i+"h"+-e+"Z"},toString:function(){return this._}};var L=Math.abs,q=Math.atan2,S=Math.cos,j=Math.max,I=Math.min,O=Math.sin,B=Math.sqrt,Z=1e-12,H=Math.PI,Q=H/2,D=2*H;function F(t){return t>=1?Q:t<=-1?-Q:Math.asin(t)}function G(t){return t.innerRadius}function J(t){return t.outerRadius}function K(t){return t.startAngle}function U(t){return t.endAngle}function V(t){return t&&t.padAngle}function W(t,n,e,i,r,o,c){var a=t-e,s=n-i,h=(c?o:-o)/B(a*a+s*s),u=h*s,l=-h*a,f=t+u,_=n+l,y=e+u,x=i+l,p=(f+y)/2,d=(_+x)/2,g=y-f,v=x-_,b=g*g+v*v,m=r-o,$=f*x-y*_,M=(v<0?-1:1)*B(j(0,m*m*b-$*$)),T=($*v-g*M)/b,w=(-$*g-v*M)/b,A=($*v+g*M)/b,z=(-$*g+v*M)/b,E=T-p,N=w-d,P=A-p,C=z-d;return E*E+N*N>P*P+C*C&&(T=A,w=z),{cx:T,cy:w,x01:-u,y01:-l,x11:T*(r/m-1),y11:w*(r/m-1)}}function X(){var t=G,n=J,e=k(0),i=null,r=K,o=U,c=V,a=null;function s(){var s,h,u,l=+t.apply(this,arguments),f=+n.apply(this,arguments),_=r.apply(this,arguments)-Q,y=o.apply(this,arguments)-Q,x=L(y-_),p=y>_;if(a||(a=s=R()),fZ)if(x>D-Z)a.moveTo(f*S(_),f*O(_)),a.arc(0,0,f,_,y,!p),l>Z&&(a.moveTo(l*S(y),l*O(y)),a.arc(0,0,l,y,_,p));else{var d,g,v=_,b=y,m=_,$=y,M=x,T=x,w=c.apply(this,arguments)/2,A=w>Z&&(i?+i.apply(this,arguments):B(l*l+f*f)),z=I(L(f-l)/2,+e.apply(this,arguments)),E=z,N=z;if(A>Z){var P=F(A/l*O(w)),C=F(A/f*O(w));(M-=2*P)>Z?(m+=P*=p?1:-1,$-=P):(M=0,m=$=(_+y)/2),(T-=2*C)>Z?(v+=C*=p?1:-1,b-=C):(T=0,v=b=(_+y)/2)}var k=f*S(v),j=f*O(v),G=l*S($),J=l*O($);if(z>Z){var K,U=f*S(b),V=f*O(b),X=l*S(m),Y=l*O(m);if(x1?0:u<-1?H:Math.acos(u))/2),ot=B(K[0]*K[0]+K[1]*K[1]);E=I(z,(l-ot)/(rt-1)),N=I(z,(f-ot)/(rt+1))}}T>Z?N>Z?(d=W(X,Y,k,j,f,N,p),g=W(U,V,G,J,f,N,p),a.moveTo(d.cx+d.x01,d.cy+d.y01),NZ&&M>Z?E>Z?(d=W(G,J,U,V,l,-E,p),g=W(k,j,X,Y,l,-E,p),a.lineTo(d.cx+d.x01,d.cy+d.y01),E{if(t.angle||t.total){let t=0;e("arcs",c=r.map(n=>{const e={innerRadius:20,outerRadius:40,startAngle:t,endAngle:t+=i*n.size/a};return{color:n.color,label:n.label,d:o(e),centroid:o.centroid(e)}}))}}),e("total",a=r.reduce((t,n)=>t+n.size,0)),{angle:i,arcs:c,Math:Math,input_change_input_handler:function(){var t;t=this.value,e("angle",i=""===t?void 0:+t)}}}it.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:et(this,this._t0,nt(this,this._t0))}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){var e=NaN;if(n=+n,(t=+t)!==this._x1||n!==this._y1){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,et(this,nt(this,e=tt(this,t,n)),e);break;default:et(this,this._t0,e=tt(this,t,n))}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n,this._t0=e}}},(function(t){this._context=new rt(t)}.prototype=Object.create(it.prototype)).point=function(t,n){it.prototype.point.call(this,n,t)},rt.prototype={moveTo:function(t,n){this._context.moveTo(n,t)},closePath:function(){this._context.closePath()},lineTo:function(t,n){this._context.lineTo(n,t)},bezierCurveTo:function(t,n,e,i,r,o){this._context.bezierCurveTo(n,t,i,e,o,r)}};document.body.innerHTML="",new class extends z{constructor(t){super(),A(this,t,st,at,o,[])}}({target:document.body,props:{segments:[{size:5,label:"this thing",color:"rgb(100,180,200)"},{size:8,label:"that thing",color:"rgb(150,200,250)"},{size:11,label:"another thing",color:"rgb(80,100,150)"}]}})}(); 2 | --------------------------------------------------------------------------------