Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomhermans/3adaa8091228d5d172daf1a10438f1a0 to your computer and use it in GitHub Desktop.
Save tomhermans/3adaa8091228d5d172daf1a10438f1a0 to your computer and use it in GitHub Desktop.
3 fork: distributed dots on a half circle in SVG + lines from center
<div>
<h3>WIP exp - Draw dots based on total number, spread over circle:
<!-- <span class="error">Fails because adding to group instead of generated. </span> -->
</h3>
<!-- <p>set object with connections, generate equal amount of point, draw them with corresponding letter <br>and (WIP) connect them according to the graph.</p> -->
</div>
<main>
<svg id="svg" viewBox="-5 -5 1010 1210" xmlns="http://www.w3.org/2000/svg">
<circle cx="500" cy="500" r="500" stroke="#ddd" fill="none" stroke-width="8" />
<circle cx="500" cy="500" r="400" stroke="#ddd" fill="none" stroke-width="8" />
<line x1="500" y1="0" x2="500" y2="1000" stroke="#ddd" stroke-width="8" />
<line y1="500" x1="0" y2="500" x2="1000" stroke="#ddd" stroke-width="8" />
<line y1="1000" x1="500" y2="300" x2="500" stroke="hsl(240,50%,40%)" stroke-width="30" />
<!-- <path d="M50,50 L0,50 A50,50 0 0,1 50,0 Z" fill="none" stroke="blue" /> -->
<!-- <path d="M100,50 A50,50 0 0,1 50,0 Z" fill="none" stroke="blue" /> -->
<g id="generated"></g>
<symbol viewBox="0 0 16 16" id="down-arrow">
<polygon points="11,6 7.5,9.5 4,6 3,7 7.5,11.5 12,7"></polygon>
</symbol>
</svg>
<div id="buttons" class="buttons">
<input id="inpnumber" type="number" value="8" />
<button id="regenerate">Regenerate</button>
</div>
</main>
// import https://codepen.io/tomhermans/pen/PoJQyJO.js
const PARAMS = {
// angle1: 0,
// angle2: 30,
number: 8,
radius: 400,
svgYcen: 900,
yDelta: 140,
strokeWidth: 25,
degrees: 135,
hue: 87,
lig1: 54
// background: "#bada55"
};
let svgns = "http://www.w3.org/2000/svg",
svg = document.getElementById("svg"),
inpnumber = document.getElementById("inpnumber"),
generated = document.getElementById("generated"),
radius = 400,
svgXcen = 500,
svgYcen = 900,
yDelta = 140,
yDeltaDeviate = 0.2 * PARAMS.yDelta;
//. Tweakpane
const minmax = { min: 0, max: 1000, step: 1 };
const minmax2 = { min: 0, max: 50, step: 1 };
const pane = new Tweakpane.Pane();
const f1 = pane.addFolder({
title: "controls"
});
// svgProps = svg.getBoundingClientRect(); console.log(svgProps)
let svgviewbox = svg.getAttribute("viewBox").split(/\s+|,/);
// console.log(svgviewbox);
let svgvb = svg.viewBox.baseVal;
function setRandomPoints() {
let points = [];
generated.innerHTML = "";
let objlen = PARAMS.number; //4; //Object.keys(graph).length;
let cirlen = 2 * Math.PI * PARAMS.radius;
let degrees = PARAMS.degrees; //getRandomInt(0, 40); // start degree
var angle = (degrees * Math.PI) / 180;
// console.log({ angle });
let anglestep = 315 / objlen; // angle between dots
// console.log(cirlen.toFixed(2), (cirlen / objlen).toFixed(2));
// console.log({ anglestep });
for (i = 0; i < objlen; i++) {
let tempArr = [];
let dotX =
Math.round(svgvb.width / 2 + PARAMS.radius * Math.cos(angle)) - 5;
let dotY =
Math.round(svgvb.width / 2 + PARAMS.radius * Math.sin(angle)) - 5;
points.push([dotX, dotY]);
degrees = degrees + anglestep;
var angle = (degrees * Math.PI) / 180;
// CREATE GROUP
let group = createGroup(i);
// DRAW DOTS AND LINES
drawDot(dotX, dotY, PARAMS.radius / 5, PARAMS.hue, i, group);
drawLine(dotX, dotY, svgXcen, PARAMS.svgYcen, PARAMS.hue, i, group);
generated.appendChild(group);
}
// console.log(points);
// return points;
}
setRandomPoints();
createUseElem(1, 100, 100);
function createUseElem(i, w, h) {
var x = (svgXcen * 2 - w) / 2;
var useElem = document.createElementNS(svgns, "use");
useElem.setAttributeNS(null, "style", `fill: hsla(120, 90%, 50%, .8);`);
useElem.setAttribute("width", w);
useElem.setAttribute("height", h);
useElem.setAttribute("x", x);
useElem.setAttributeNS(
"http://www.w3.org/1999/xlink",
"xlink:href",
"#down-arrow"
);
generated.appendChild(useElem);
}
function createGroup(i) {
var group = document.createElementNS(svgns, "g");
group.setAttribute("id", "g" + i);
// group.setAttributeNS(null, "fill", "green");
// group.setAttributeNS(null, "stroke", "red");
return group;
}
function drawDot(x, y, r, hue = 0, i, group) {
// console.log("drawcir", group);
var circle = document.createElementNS(svgns, "circle");
circle.setAttribute("id", "cir" + i);
circle.setAttributeNS(null, "cx", x);
circle.setAttributeNS(null, "cy", y);
circle.setAttributeNS(null, "r", r);
circle.setAttributeNS(
null,
"style",
`fill: hsla(${hue + i * 3}, 90%, 50%, 1);`
);
group.appendChild(circle);
}
function drawLine(x, y, x2 = 50, y2 = 50, hue = 0, i, group) {
var inpval = parseInt(PARAMS.number);
var newLine = document.createElementNS("http://www.w3.org/2000/svg", "line");
newLine.setAttribute("id", "line" + i);
newLine.setAttribute("x1", x);
newLine.setAttribute("y1", y);
newLine.setAttribute("x2", x2);
newLine.setAttribute("stroke-width", PARAMS.strokeWidth);
if (i < Math.floor(inpval / 2)) {
newLine.setAttribute(
"y2",
y2 -
i *
getRandomInt(
PARAMS.yDelta - yDeltaDeviate,
PARAMS.yDelta + yDeltaDeviate
)
);
} else {
newLine.setAttribute(
"y2",
y2 +
(i - (PARAMS.number - 1)) *
getRandomInt(
PARAMS.yDelta - yDeltaDeviate,
PARAMS.yDelta + yDeltaDeviate
)
);
}
newLine.setAttribute("stroke", "black");
newLine.setAttributeNS(
null,
"style",
`stroke: hsla(${PARAMS.hue + i * 3}, 90%, 50%, 1);`
);
group.appendChild(newLine);
}
// Regenerate btn
const btn = document.querySelector("#regenerate");
btn.addEventListener("click", () => {
points = [];
generated.innerHTML = "";
// console.log("btn pressed");
setRandomPoints();
});
// update dots when input changes
inpnumber.addEventListener("input", (e) => {
console.clear();
PARAMS.number = e.target.value;
points = [];
console.log("inp change");
generated.innerHTML = "";
// console.log("btn pressed");
setRandomPoints();
});
// Tweakpane
for (const [property, value] of Object.entries(PARAMS)) {
// console.log("xxx", `${property}: ${PARAMS[property]}`);
// if (property === "hue1") {
// pane
// .addInput(PARAMS, `${property}`, {
// min: 0,
// max: 360,
// step: 1,
// })
// .on("change", (val) => {
// // PARAMS.property = val.value;
// generate();
// });
// } else
if (
property === "strokeWidth" ||
property === "number" ||
property === "dlig"
) {
pane.addInput(PARAMS, `${property}`, minmax2).on("change", (val) => {
// PARAMS.property = val.value;
points = [];
console.log(`${property}`, val);
generated.innerHTML = "";
setRandomPoints();
});
} else {
pane.addInput(PARAMS, `${property}`, minmax).on("change", (val) => {
// setCustomProp(`${property}`, val.value);
points = [];
console.log(`${property}`, val);
generated.innerHTML = "";
setRandomPoints();
});
}
}
<script src="https://codepen.io/tomhermans/pen/PoJQyJO.js"></script>
<script src="https://cdn.jsdelivr.net/npm/tweakpane@3.0.5/dist/tweakpane.min.js"></script>
svg {
max-width: 70vw;
max-height: 70vh;
outline: 1px dashed red;
text {
font-size: 4px;
fill: #333;
}
line,
circle {
transform-box: fill-box;
// outline: 1px dashed red;
}
}
* {
// outline: 1px dashed red;
}
main {
display: grid;
place-items: center;
min-height: 70vh;
}
body {
padding: 1rem;
}
svg {
line,
circle {
transition: all 0.25s;
}
}
line {
transform-origin: center;
&[id^="line"] {
// stroke-width: 2px;
&:hover {
// border: 2px solid green;
stroke-width: 4px;
stroke: green !important;
// transform: scale(3);
}
}
}
circle {
transform-origin: center;
&[id^="cir"] {
&:hover {
border: 2px solid green;
fill: green !important;
transform: scale(1.3);
}
}
}
g:not(#generated) {
&[id^="g"] {
&:hover {
line {
stroke-width: 20px;
stroke: red !important;
}
circle {
border: 2px solid red;
fill: green !important;
transform: scale(1.3);
}
}
}
circle {
transform-origin: center;
&[id^="cir"] {
&:hover {
border: 2px solid green;
fill: green !important;
transform: scale(1.2);
}
}
}
}
// sass loop for animation-delay: 2s;
@for $i from 0 through 8 {
#cir#{$i} {
animation: pop-once 1s;
animation-delay: $i * 0.2s;
}
}
.error {
color: red;
}
@keyframes pop-once {
0% {
opacity: 0.75;
}
60% {
opacity: 1;
transform: scale(1.3);
}
100% {
opacity: 0.75;
}
}
input {
caret-color: red;
caret-shape: block;
}
@tomhermans
Copy link
Author

tree builder

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