shape-poly
Version:
Make CSS Polygon Shape
310 lines (266 loc) • 9.19 kB
JavaScript
/*
Copyright (c) 2018 Daybrush
license: MIT
author: Daybrush
repository: https://github.com/daybrush/shape-poly
@version 0.0.9
*/
var _a;
var TOP = "top";
var BOTTOM = "bottom";
var LEFT = "left";
var RIGHT = "right";
var REVERSE = (_a = {}, _a[TOP] = BOTTOM, _a[BOTTOM] = TOP, _a[LEFT] = RIGHT, _a[RIGHT] = LEFT, _a);
var POLY_CLASS = "__shape-poly";
var SIDE_CLASS = POLY_CLASS + "-side";
var POSITION_ABSOLUTE = "position:absolute;";
var SIDE_CSS = POSITION_ABSOLUTE + "width:100%;height:100%;border-radius:inherit;\nbackground-color:inherit;transform-origin:inherit;";
function splitUnit(text) {
var matches = /^([^\d|e|\-|\+]*)((?:\d|\.|-|e-|e\+)+)(\S*)$/g.exec(text);
if (!matches) {
return {
unit: "",
value: NaN
};
}
var value = matches[2];
var unit = matches[3];
return {
unit: unit,
value: parseFloat(value)
};
}
function getTransformOrigin(strokeWidth, isVertical) {
var x = isVertical ? strokeWidth : "50%";
var y = isVertical ? "50%" : strokeWidth;
return "transform-origin:" + x + " " + y + ";";
}
function getHTML(no, style, content) {
if (content === void 0) {
content = "";
}
return "<div class=\"" + SIDE_CLASS + no + "\" style=\"" + style + "\">" + content + "</div>";
}
function makeDOM(tag, className) {
var el = document.createElement(tag);
el.className = className;
return el;
}
function getSin(side) {
// sin([n / 2] * 180 / n)
return Math.sin(Math.floor(side / 2) * Math.PI / side);
}
function getCos(side) {
// cos(180 / n)
return Math.cos(Math.PI / side);
}
function getStarAngle(side, radius) {
var cos = getCos(side);
return 100 * cos <= radius ? 0 : Math.atan((cos - radius / 100) / Math.sin(Math.PI / side)) / Math.PI * 180;
}
function getSideSize(side, split, starAngle, strokeWidth) {
var starRatio = starAngle ? 1 / Math.cos(starAngle * Math.PI / 180) : 1;
var ratio = 1 / split;
if (side > 4) {
var sin = Math.sin(Math.PI / side);
var cos = Math.cos(Math.PI / side);
if (side % 4 === 0) {
// 2 * r * cos(180 / n) = w
// 2 * r * sin(180 / n) = size
ratio *= sin / cos;
} else if (side % 2 === 0) {
ratio *= sin;
} else {
// 2 * r * sin([n /2] * 180 / n) = w
// 2 * r * sin(180 / n) = size
ratio *= sin / getSin(side);
}
} else if (split === 1) {
return "100%";
}
ratio *= starRatio;
return "calc(100% * " + ratio + " - " + strokeWidth + " * " + ratio + " + " + strokeWidth + ")";
}
function getHeight(side, strokeWidth, isVertical) {
if (side % 4 === 0) {
return "100%";
}
var cos = getCos(side);
var ratio = 0;
if (side % 2 === 0) {
// w * cos = h (vertical)
// w / cos = h (horizontal)
ratio = isVertical ? cos : 1 / cos;
} else {
var sin = getSin(side);
if (isVertical) {
// 2 * r * sin([n /2] * 180 / n) = w
ratio = 0.5 / sin * (1 + cos);
} else {
// r * (1 + cos(180 / n)) = w
ratio = 2 * 1 / (1 + cos) * sin;
}
}
return "calc(100% * " + ratio + " + " + strokeWidth + " * " + (1 - ratio) + ")";
}
function getFirstTransform(side, split, isVertical, starAngle, strokeValue, strokeUnit) {
var translateProperty = isVertical ? "X" : "Y";
var cos = Math.cos(starAngle * Math.PI / 180);
var arr = [];
arr.push("translate" + translateProperty + "(-" + 50 * cos * split + "%)");
if (split > 1) {
arr.push("translate" + translateProperty + "(" + strokeValue / 2 * (cos * split - 1) + strokeUnit + ")");
}
if (starAngle !== 0) {
arr.push("rotate(" + starAngle + "deg)");
}
return "transform:" + arr.join(" ") + ";";
}
function getAttribute(el, name) {
return el.getAttribute("data-" + name) || undefined;
}
function dom(el) {
var strokeWidth = getAttribute(el, "stroke-width");
var stroke = getAttribute(el, "stroke");
var direction = getAttribute(el, "direction");
var side = getAttribute(el, "side");
var split = getAttribute(el, "split");
var starRadius = getAttribute(el, "star-radius");
side && (side = parseFloat(side));
split && (split = parseFloat(split));
starRadius && (starRadius = parseFloat(starRadius));
return poly({
side: side,
split: split,
starRadius: starRadius,
strokeWidth: strokeWidth,
direction: direction,
stroke: stroke,
container: el
});
}
function css(_a) {
var _b = _a.strokeWidth,
strokeWidth = _b === void 0 ? 0 : _b,
_c = _a.side,
side = _c === void 0 ? 3 : _c,
_d = _a.split,
split = _d === void 0 ? 1 : _d,
_e = _a.starRadius,
starRadius = _e === void 0 ? 100 : _e,
_f = _a.stroke,
stroke = _f === void 0 ? "black" : _f,
_g = _a.direction,
direction = _g === void 0 ? BOTTOM : _g;
var splitCount = split * (starRadius === 100 ? 1 : 2);
var _h = splitUnit("" + strokeWidth),
strokeUnit = _h.unit,
strokeValue = _h.value;
var half = "" + strokeValue / 2 + strokeUnit;
var reverseDirection = REVERSE[direction];
var isVertical = direction === TOP || direction === BOTTOM;
var directionProperty = isVertical ? LEFT : TOP;
var otherDirectionProperty = isVertical ? TOP : LEFT;
var padding = getHeight(side, strokeWidth, isVertical);
var sign = direction === TOP || direction === RIGHT ? -1 : 1;
var starAngle = starRadius === 100 ? 0 : getStarAngle(side, starRadius);
var sideWidth = getSideSize(side, splitCount, starAngle, strokeWidth);
var width = isVertical ? sideWidth : strokeWidth;
var height = isVertical ? strokeWidth : sideWidth;
var externalAngle = 360 / side + 2 * starAngle;
var transformSplit = getFirstTransform(side, splitCount, isVertical, sign * starAngle, strokeValue, strokeUnit);
var sides = [];
sides.push(reverseDirection + ":0;\n " + otherDirectionProperty + ":auto;\n " + directionProperty + ":50%;" + transformSplit + getTransformOrigin(half, isVertical) + "\n width:" + width + ";height:" + height + ";border-radius:" + half + ";background:" + stroke + ";");
for (var i = 0; i < side; ++i) {
for (var j = 0; j < splitCount; ++j) {
var no = i * splitCount + j;
if (no === 0) {
continue;
}
var transform = j === 0 ? "transform:rotate(" + sign * externalAngle + "deg)" : starAngle && j === splitCount / 2 ? "transform:rotate(" + -sign * 2 * starAngle + "deg)" : "transform:none;";
sides.push(otherDirectionProperty + ":auto;" + directionProperty + ": calc(100% - " + strokeWidth + ");" + transform);
}
}
return {
sides: sides,
percent: "padding-top:" + padding
};
}
function be(el, _a) {
var _b = _a.strokeWidth,
strokeWidth = _b === void 0 ? 0 : _b,
_c = _a.side,
side = _c === void 0 ? 3 : _c,
_d = _a.starRadius,
starRadius = _d === void 0 ? 100 : _d,
stroke = _a.stroke,
_e = _a.direction,
direction = _e === void 0 ? BOTTOM : _e;
var sideElements = el.querySelectorAll("." + SIDE_CLASS);
var length = sideElements.length;
var split = length / (side * (starRadius !== 100 ? 2 : 1));
if (!length || split % 1) {
return;
}
var style = getComputedStyle(sideElements[0]);
var elStrokeWidth = strokeWidth || direction === TOP || direction === BOTTOM ? style.height : style.width;
var elStroke = stroke || style.backgroundColor;
var percentElement = el.querySelector("." + SIDE_CLASS + "-percent");
var _f = css({
strokeWidth: elStrokeWidth,
side: side,
split: split,
starRadius: starRadius,
stroke: elStroke,
direction: direction
}),
sides = _f.sides,
percent = _f.percent;
sides.forEach(function (sideCSS, i) {
sideElements[i].style.cssText += sideCSS;
});
percentElement.style.cssText += percent;
}
function poly(_a) {
var _b = _a.className,
className = _b === void 0 ? POLY_CLASS : _b,
_c = _a.strokeWidth,
strokeWidth = _c === void 0 ? 0 : _c,
_d = _a.side,
side = _d === void 0 ? 3 : _d,
_e = _a.split,
split = _e === void 0 ? 1 : _e,
_f = _a.starRadius,
starRadius = _f === void 0 ? 100 : _f,
_g = _a.stroke,
stroke = _g === void 0 ? "black" : _g,
_h = _a.direction,
direction = _h === void 0 ? BOTTOM : _h,
_j = _a.container,
container = _j === void 0 ? makeDOM("div", className) : _j;
var _k = css({
strokeWidth: strokeWidth,
side: side,
split: split,
starRadius: starRadius,
stroke: stroke,
direction: direction
}),
sides = _k.sides,
percent = _k.percent;
var html;
for (var i = sides.length - 1; i >= 1; --i) {
html = getHTML(" " + SIDE_CLASS + i, SIDE_CSS + sides[i], html);
}
html = getHTML(" " + SIDE_CLASS + "0", POSITION_ABSOLUTE + "display:inline-block;" + sides[0], html);
var percentHTML = getHTML("-percent", "position:relative;width:100%;" + percent);
var position = getComputedStyle(container).position;
if (!position || position === "static") {
container.style.position = "relative";
}
container.insertAdjacentHTML("beforeend", html + percentHTML);
return container;
}
var VERSION = "0.0.9";
export { dom, css, be, poly, VERSION };
//# sourceMappingURL=shapepoly.esm.js.map