ZF - svg web

by PhilQ

HTML

<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<script type="text/x-template" id="graph-web-template">
	<svg :width="w" :height="h" xmlns="http://www.w3.org/2000/svg">
		<defs xmlns="http://www.w3.org/2000/svg">
			<filter id="insetglow" x="-50%" y="-50%" width="200%" height="200%">
				<feComponentTransfer in=SourceAlpha>
					<feFuncA type="table" tableValues="0.1 0" />
				</feComponentTransfer>
				<feGaussianBlur stdDeviation="0"/>
				<feOffset dx="1" dy="1" result="offsetblur"/>
				<feFlood flood-color="rgb(255, 255, 255)" result="color"/>
				<feComposite in2="offsetblur" operator="in"/>
				<feComposite in2="SourceAlpha" operator="in" />
				<feMerge>
					<feMergeNode in="SourceGraphic" />
					<feMergeNode />
				</feMerge>
			</filter> 

			<filter id="insetshadow" x="-50%" y="-50%" width="200%" height="200%">
				<feComponentTransfer in=SourceAlpha>
					<feFuncA type="table" tableValues="0.3 0" />
				</feComponentTransfer>
				<feGaussianBlur stdDeviation="0"/>
				<feOffset dx="-1" dy="-1" result="offsetblur"/>
				<feFlood flood-color="rgb(0, 0, 0)" result="color"/>
				<feComposite in2="offsetblur" operator="in"/>
				<feComposite in2="SourceAlpha" operator="in" />
				<feMerge>
					<feMergeNode in="SourceGraphic" />
					<feMergeNode />
				</feMerge>
			</filter> 

			<filter id="dropshadow" width="200%" height="200%">
			  <feGaussianBlur in="SourceAlpha" stdDeviation="3"/> 
			  <feOffset dx="0" dy="2" result="offsetblur"/>
			  <feComponentTransfer>
				<feFuncA type="linear" slope="0.3"/>
			  </feComponentTransfer>
			  <feMerge> 
				<feMergeNode/>
				<feMergeNode in="SourceGraphic"/> 
			  </feMerge>
			</filter>

			<filter id="textglow" x="-50%" y="-50%" width="200%" height="200%">
				<feOffset result="offOut" in="SourceGraphic" dx="0" dy="0" />
				<feFlood result="maskColor" flood-color="#ffffff" flood-opacity="1" />
				<feComposite result="maskOut" operator="in" in="maskColor" in2="offOut"...

SCSS

*, *:before, *:after { box-sizing: border-box; margin: 0; padding: 0; }

.graph-web-parent {
	.graph-web-poly {
		.on {
			display: none;
		}
		&:hover .on {
			display: inline;
		}
	}
	&.over {
		path:not(.y) {
			stroke-opacity: 0.2;
			//fill-opacity: 0.2;
		}

		.graph-web-poly:hover {
			path {
				stroke-opacity: 1;
				stroke-width: 4;
				//fill: #ffffff;
				//fill-opacity: 0.8;
			}
			circle {
				stroke: #ffffff;
				stroke-width: 2;

				&:hover {
					r: 10;
				}
			}
			* {
				filter: url(#dropshadow);
			}
		}
	}
}

JavaScript

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
    var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;
    return {
        x: centerX + (radius * Math.cos(angleInRadians)),
        y: centerY + (radius * Math.sin(angleInRadians))
    };
}

// The raw data to observe
var chartdata = {
    w: 12,
    h: 8,
    blocksize: 0,
    margin: 30,
    stroke: 2, //width
    fill: 0, //opacity
    stacked: false,
    percentage: false,
    axes: [
        'A', 'B', 'C', 'D', 'E'
    ],
    values: [
        { label: 'Groep 1', color: '#cc0000', values: [
            7,
            2,
            1,
            2,
            1,
        ] },
        { label: 'Groep 2', color: '#00cc00', values: [
            2,
            1,
            2,
            1,
            2,
        ] },
        { label: 'Groep 3', color: '#0000cc', values: [
            3,
            7,
            15,
            9,
            3,
        ] },
    ],
};


// A resusable polygon graph component
Vue.component('graph-web', {
    props: ['chartdata','blocksize'],
    template: '#graph-web-template',
    methods: {
        polar_to_cartesian: function (centerX, centerY, radius, angleInDegrees) {
            var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;
            return {
                x: centerX + (radius * Math.cos(angleInRadians)),
                y: centerY + (radius * Math.sin(angleInRadians))
            };
        },
        in_front: function (event) {
            $( event.target.parentNode ).addClass('over');
            event.target.parentNode.appendChild( event.target );
        },
        off_front: function (event) {
            $( event.target.parentNode ).removeClass('over');
        },
        get_path: function (points, translation_x, translation_y) {
            return 'M ' + (points.map(function (point, i) {
                    return Math.round(point.x + translation_x) + ',' + Math.round(point.y + translation_y)
               ...