Skip to content

Instantly share code, notes, and snippets.

@oelna
Created December 1, 2023 15:54
Show Gist options
  • Save oelna/4fa6c52df0ab43e6a036d7904f99af8d to your computer and use it in GitHub Desktop.
Save oelna/4fa6c52df0ab43e6a036d7904f99af8d to your computer and use it in GitHub Desktop.
work-in-progress interactive flavor-profile generator in SVG and JS
Display the source blob
Display the rendered blob
Raw
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 400 300" xml:space="preserve">
<style type="text/css">
#spread {
width: 400px;
height: 300px;
fill: #fff;
}
.ring {
fill: none;
stroke: #fff;
}
.point {
fill: #000;
stroke: #fff;
cursor: pointer;
}
/*
.point:hover {
fill: lightgreen;
}
*/
.point.highlight {
/* fill: lightgreen; */
stroke-width: 1.1;
}
.point.current {
fill: #00ddb1;
}
.point.selected {
fill: #000;
}
.w0 { stroke-width: 0.6; }
.w1 { stroke-width: 1.1; }
.shape {
fill: #00ddb1;
}
</style>
<rect width="100%" height="100%" fill="#000"/>
<g id="circles">
</g>
<script><![CDATA[
var xmlns = "http://www.w3.org/2000/svg";
var centerX = 100;
var centerY = 100;
function drawCircle (cx, cy, radius, steps, weight) {
var c = document.createElementNS(xmlns, 'circle');
c.setAttributeNS(null, "cx", cx + 'px');
c.setAttributeNS(null, "cy", cy + 'px');
c.setAttributeNS(null, "r", radius + 'px');
c.setAttributeNS(null, "class", 'ring '+weight);
var g = document.getElementById('circles');
g.appendChild(c);
var points = [];
// points
for (let i=0; i<steps; i++) {
const rad = (360/steps*i) * (Math.PI/180);
var x = centerX + Math.cos(rad) * radius;
var y = centerY + Math.sin(rad) * radius;
drawPoint(x, y, 4, i, weight);
}
}
function drawPoint (x, y, size, index, weight) {
var c = document.createElementNS(xmlns, 'circle');
c.setAttributeNS(null, "cx", x.toFixed(2) + 'px');
c.setAttributeNS(null, "cy", y.toFixed(2) + 'px');
c.setAttributeNS(null, "r", (size/2) + 'px');
c.setAttributeNS(null, "data-index", index);
c.setAttributeNS(null, "class", 'point '+weight);
var g = document.getElementById('circles');
g.appendChild(c);
}
function redrawShape (point) {
var shape = document.querySelector('.shape');
const shapePoints = shape.getAttribute('points').split(' ');
const index = point.getAttribute('data-index');
// console.log(shapePoints, point, index);
shapePoints[index] = point.getAttribute('cx').slice(0, -2)+','+point.getAttribute('cy').slice(0, -2);
shape.setAttribute('points', shapePoints.join(' '));
}
function drawWheel (cx, cy, maxRadius, minRadius, steps, points) {
// polygon fill
var shapePoints = [];
for (let i=0; i<points; ++i) {
shapePoints[i] = cx+','+cy;
}
var p = document.createElementNS(xmlns, 'polygon');
// console.log(shapePoints.join(' '));
p.setAttributeNS(null, "points", shapePoints.join(' '));
p.setAttributeNS(null, "class", 'shape');
var g = document.getElementById('circles');
g.appendChild(p);
for (let i=0; i<steps; i++) {
var r = (maxRadius-minRadius)/steps*i + minRadius;
var weight = (i == steps-1) ? 'w1' : 'w0';
drawCircle(cx, cy, r, points, weight);
}
}
drawWheel(centerX, centerY, 60, 12, 5, 12);
document.addEventListener('pointerover', function (event) {
// console.log(document.querySelectorAll('circle.point'));
document.querySelectorAll('circle.point').forEach(function (ele, i) {
ele.classList.remove('highlight');
ele.classList.remove('current');
});
if (event.target.tagName.toLowerCase() != 'circle') return;
if (!event.target.classList.contains('point')) return;
// console.log(event.target.classList.contains('point'));
const point = event.target.closest('circle.point');
const index = point.getAttribute('data-index');
document.querySelectorAll('circle.point[data-index="'+index+'"]').forEach(function (ele, i) {
ele.classList.add('highlight');
});
point.classList.add('current');
});
document.addEventListener('click', function (event) {
if (event.target.tagName.toLowerCase() != 'circle') return;
if (!event.target.classList.contains('point')) return;
const point = event.target.closest('circle.point');
const index = point.getAttribute('data-index');
document.querySelectorAll('circle.point[data-index="'+index+'"]').forEach(function (ele, i) {
ele.classList.remove('selected');
});
point.classList.add('selected');
// redraw shape
redrawShape(point);
});
]]></script>
</svg>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment