Last active
October 12, 2015 09:15
-
-
Save jarek-foksa/151418a0b4ab6ebab330 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @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