Skip to content

Instantly share code, notes, and snippets.

@jarek-foksa
Last active October 12, 2015 09:15
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 jarek-foksa/151418a0b4ab6ebab330 to your computer and use it in GitHub Desktop.
Save jarek-foksa/151418a0b4ab6ebab330 to your computer and use it in GitHub Desktop.
// @copyright
// © 2015 Jarosław Foksa
import {createElement} from "../utils/dom";
import {round, sin, cos, degToRad, PI} from "../utils/math";
import {collapseWhitespace} from "../utils/string";
const STAR_PATH_DATA_ATTRIBUTES = [
"data-bx-cx",
"data-bx-cy",
"data-bx-r1",
"data-bx-r2",
"data-bx-arms",
"data-bx-shift"
];
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// @info
// Generate path data for star with given coordinates
// @src
// http://svg-whiz.com/svg/starPrimative.svg
// @type
// (number, number, number, number, number, number, string) => string
let starCoordsToPathData = (cx, cy, r1, r2, arms, shift) => {
let d = "";
for (let s = 0; s <= arms; s += 1) {
let angle = (2 * PI * (s / arms)) - (PI / 2);
let x = (r2 * cos(angle)) + cx;
let y = (r2 * sin(angle)) + cy;
x = round(x, 8);
y = round(y, 8);
if (s === 0) {
d += `M ${x} ${y}`;
}
else {
d += ` L ${x} ${y}`;
}
angle = ((2 * PI * (s / arms)) + (PI/arms)) - (PI/2) + degToRad(shift);
x = (r1 * cos(angle)) + cx;
y = (r1 * sin(angle)) + cy;
x = round(x, 8);
y = round(y, 8);
d += ` L ${x} ${y}`;
}
return d;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class BXStarPathElement extends SVGPathElement {
static fromSVGPath(path) {
let cx = path.hasAttribute("data-bx-cx") ? parseFloat(path.getAttribute("data-bx-cx")) : 0;
let cy = path.hasAttribute("data-bx-cy") ? parseFloat(path.getAttribute("data-bx-cy")) : 0;
let r1 = path.hasAttribute("data-bx-r1") ? parseFloat(path.getAttribute("data-bx-r1")) : 0;
let r2 = path.hasAttribute("data-bx-r2") ? parseFloat(path.getAttribute("data-bx-r2")) : 0;
let arms = path.hasAttribute("data-bx-arms") ? parseFloat(path.getAttribute("data-bx-arms")) : 5;
let shift = path.hasAttribute("data-bx-shift") ? parseFloat(path.getAttribute("data-bx-shift")) : 0;
let d = starCoordsToPathData(cx, cy, r1, r2, arms, shift);
if (d !== path.getAttribute("d")) {
return null;
}
else {
let starPath = createElement("svg:path", "bx-starpath");
for (let {name, value} of path.attributes) {
if (name !== "d" && name !== "data-bx-is") {
starPath.setAttribute(name, value);
}
}
return starPath;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
createdCallback() {
this._update();
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue === newValue) {
return;
}
else if (name.startsWith("data-bx-")) {
this._update();
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// @info
// X coordinate of the star center point.
// @property
// reflected
// @type
// number
// @default
// 0
get cx() {
return this.hasAttribute("data-bx-cx") ? parseFloat(this.getAttribute("data-bx-cx")) : 0;
}
set cx(cx) {
this.setAttribute("data-bx-cx", cx);
}
// @info
// Y coordinate of the star center point.
// @property
// reflected
// @type
// number
// @default
// 0
get cy() {
return this.hasAttribute("data-bx-cy") ? parseFloat(this.getAttribute("data-bx-cy")) : 0;
}
set cy(cy) {
this.setAttribute("data-bx-cy", cy);
}
// @info
// The inner radius of the star (inradius).
// @property
// reflected
// @type
// number
// @default
// 0
get r1() {
return this.hasAttribute("data-bx-r1") ? parseFloat(this.getAttribute("data-bx-r1")) : 0;
}
set r1(r1) {
this.setAttribute("data-bx-r1", r1);
}
// @info
// The outer radius of the star (circumradius).
// @property
// reflected
// @type
// number
// @default
// 0
get r2() {
return this.hasAttribute("data-bx-r2") ? parseFloat(this.getAttribute("data-bx-r2")) : 0;
}
set r2(r2) {
this.setAttribute("data-bx-r2", r2);
}
// @info
// The number of star arms, between 3 and 10.
// @property
// reflected
// @type
// number
// @default
// 5
get arms() {
return this.hasAttribute("data-bx-arms") ? parseFloat(this.getAttribute("data-bx-arms")) : 5;
}
set arms(arms) {
this.setAttribute("data-bx-arms", arms);
}
// @info
// Value by which the star arms should be shifted, producing spiraling shape.
// @property
// reflected
// @type
// number
// @default
// 0
get shift() {
return this.hasAttribute("data-bx-shift") ? parseFloat(this.getAttribute("data-bx-shift")) : 0;
}
set shift(shift) {
this.setAttribute("data-bx-shift", shift);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// @info
// Create regular SVG <path> element.
// @type
// (string) => SVGPathElement
toSVGPath(preserveStarData = true) {
let path = createElement("svg:path");
for (let {name, value} of this.attributes) {
if (name === "is") {
if (preserveStarData) {
path.setAttribute("data-bx-is", value);
}
}
else if (STAR_PATH_DATA_ATTRIBUTES.includes(name)) {
if (preserveStarData) {
path.setAttribute(name, value);
}
}
else {
path.setAttribute(name, value);
}
}
return path;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
_update() {
let {cx, cy, r1, r2, arms, shift} = this;
let d = starCoordsToPathData(cx, cy, r1, r2, arms, shift);
this.setAttribute("d", d);
}
};
export default document.registerElement("bx-starpath", {
extends: "path",
prototype: BXStarPathElement.prototype
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment