创建一个 'New' 带有 24 点或以上爆发点的尖刺标签
Creating a 'New' spiky label with 24 or above point burst
我正在尝试制作如下图所示的点爆:
目前,我已经尝试使用伪元素进行此操作,但是,我只能生成 12 点连拍,并且无法反映图像中显示的内容。
有没有办法只用几个元素来创建点爆发?
下面是我用来尝试此解决方案的代码:
div{
width:100px;
height:100px;
background:grey;
transform:rotate(45deg);
margin:50px;
}
div:after{
position:absolute;
content:"";
background:grey;
width:100px;
height:100px;
transform:rotate(135deg);
}
div:before{
position:absolute;
content:"";
background:grey;
width:100px;
height:100px;
transform:rotate(250deg);
}
<div></div>
使用 svg 可以用一个简单的循环。我正在使用 Snap,因为它很简单。
首先使用 snap 创建一个圆,然后使用循环从我引用的圆中找到我们需要的点 this question 以查找点。找到这些点后,简单地给出这些线 points.By 改变循环中的数字,可以创建任何值的弧度值点
24点爆
var s=Snap('svg');
var circle=s.circle(50,50,30).attr({
fill:'tomato',
stroke:'tomato'
})
for (var num = 0; num < 24; num++) {
var rad1 = num * 15 * (Math.PI / 180);
var rad2 = (num+1) * 15 * (Math.PI / 180);
var rad3=(num+.5) * 15 * (Math.PI / 180);
var x1 = (30 * (Math.cos(rad1)) + 50)
var y1 = (30 * (Math.sin(rad1)) + 50)
var x2 = (40 * (Math.cos(rad3)) + 50)
var y2 = (40 * (Math.sin(rad3)) + 50)
var x3 = (30 * (Math.cos(rad2)) + 50)
var y3 = (30 * (Math.sin(rad2)) + 50)
var line=s.polyline(x1,y1,x2,y2,x3,y3).attr({
'fill':'tomato'
})
}
var text=s.text(35,50,'New').attr({
fill:'white'
})
div{
width:100vw;
height:100vh;
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div>
<svg width="100%" height="100%" viewbox="0 0 100 100">
</svg>
</div>
36点爆
var s=Snap('svg');
var circle=s.circle(50,50,30).attr({
fill:'tomato',
stroke:'tomato'
})
for (var num = 0; num < 36; num++) {
var rad1 = num * 10 * (Math.PI / 180);
var rad2 = (num+1) * 10 * (Math.PI / 180);
var rad3=(num+.5) * 10 * (Math.PI / 180);
var x1 = (30 * (Math.cos(rad1)) + 50)
var y1 = (30 * (Math.sin(rad1)) + 50)
var x2 = (40 * (Math.cos(rad3)) + 50)
var y2 = (40 * (Math.sin(rad3)) + 50)
var x3 = (30 * (Math.cos(rad2)) + 50)
var y3 = (30 * (Math.sin(rad2)) + 50)
var line=s.polyline(x1,y1,x2,y2,x3,y3).attr({
'fill':'tomato'
})
}
var text=s.text(35,50,'New').attr({
fill:'white'
})
div{
width:100vw;
height:100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div>
<svg width="100%" height="100%" viewbox="0 0 100 100">
</svg>
</div>
60点爆
var s=Snap('svg');
var circle=s.circle(50,50,30).attr({
fill:'tomato',
stroke:'tomato'
})
for (var num = 0; num < 60; num++) {
var rad1 = num * 6 * (Math.PI / 180);
var rad2 = (num+1) * 6 * (Math.PI / 180);
var rad3=(num+.5) * 6 * (Math.PI / 180);
var x1 = (30 * (Math.cos(rad1)) + 50)
var y1 = (30 * (Math.sin(rad1)) + 50)
var x2 = (40 * (Math.cos(rad3)) + 50)
var y2 = (40 * (Math.sin(rad3)) + 50)
var x3 = (30 * (Math.cos(rad2)) + 50)
var y3 = (30 * (Math.sin(rad2)) + 50)
var line=s.polyline(x1,y1,x2,y2,x3,y3).attr({
'fill':'tomato'
})
}
var text=s.text(35,50,'New').attr({
fill:'white'
})
div{
width:100vw;
height:100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div>
<svg width="100%" height="100%" viewbox="0 0 100 100">
</svg>
</div>
这也可以是动画的
var s=Snap('svg');
var circle=s.circle(50,50,30).attr({
fill:'tomato',
stroke:'tomato'
})
var g=s.g();
for (var num = 0; num < 60; num++) {
var rad1 = num * 6 * (Math.PI / 180);
var rad2 = (num+1) * 6 * (Math.PI / 180);
var rad3=(num+.5) * 6 * (Math.PI / 180);
var x1 = (30 * (Math.cos(rad1)) + 50)
var y1 = (30 * (Math.sin(rad1)) + 50)
var x2 = (40 * (Math.cos(rad3)) + 50)
var y2 = (40 * (Math.sin(rad3)) + 50)
var x3 = (30 * (Math.cos(rad2)) + 50)
var y3 = (30 * (Math.sin(rad2)) + 50)
var line=s.polyline(x1,y1,x2,y2,x3,y3).attr({
'fill':'tomato'
})
g.add(line);
}
var text=s.text(35,50,'New').attr({
fill:'white'
})
function anim(){
g.animate({
transform:'rotate(360 50,50)'
},8000,function(){
g.animate({
transform:'rotate(0 50,50)'
},0,function(){
anim()
})
})
}
anim()
div{
width:100vw;
height:100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div>
<svg width="100%" height="100%" viewbox="0 0 100 100">
</svg>
</div>
请注意,我使用了 vw
和 vh
单位来响应
这也可以用单个折线元素来制作
var s=Snap('svg');
var array=[];
for (var num = 0; num < 24; num++) {
var rad1 = num * 15 * (Math.PI / 180);
var rad2 = (num+1) * 15 * (Math.PI / 180);
var rad3=(num+.5) * 15 * (Math.PI / 180);
var x1 = (30 * (Math.cos(rad1)) + 50);
var y1 = (30 * (Math.sin(rad1)) + 50);
var x2 = (40 * (Math.cos(rad3)) + 50);
var y2 = (40 * (Math.sin(rad3)) + 50);
var x3 = (30 * (Math.cos(rad2)) + 50);
var y3 = (30 * (Math.sin(rad2)) + 50);
array.push(x1+','+y1+' '+x2+','+y2+' '+x3+','+' '+y3);
}
var line=s.polyline(array).attr({
'fill':'tomato'
})
var text=s.text(35,50,'New').attr({
fill:'white'
})
div{
width:100vw;
height:100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div>
<svg width="100%" height="100%" viewbox="0 0 100 100">
</svg>
</div>
这可以用 CSS 但在 12 点之后,需要不止一个 div。
我之前曾在项目中使用 12 点爆发作为提醒和促销风格元素。
12 点爆发
div {
background: red;
width: 80px;
height: 80px;
position: absolute;
text-align: center;
top: 20px;
left: 20px;
}
div:before,
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
height: 80px;
width: 80px;
background: red;
}
div:before {
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
}
div:after {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
-ms-transform: rotate(60deg);
-o-transform: rotate(60deg);
}
<div></div>
24点爆发
div {
background: red;
width: 80px;
height: 80px;
position: absolute;
text-align: center;
top: 20px;
left: 20px;
}
div:before, div:after {
content: "";
position: absolute;
top: 0;
left: 0;
height: 80px;
width: 80px;
background: red;
}
div:before {
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
}
div:after {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
-ms-transform: rotate(60deg);
-o-transform: rotate(60deg);
}
div:nth-child(2) {
transform: rotate(15deg)
}
<div></div>
<div></div>
36点爆发
div {
background: red;
width: 80px;
height: 80px;
position: absolute;
text-align: center;
top: 20px;
left: 20px;
}
div:before, div:after {
content: "";
position: absolute;
top: 0;
left: 0;
height: 80px;
width: 80px;
background: red;
}
div:before {
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
}
div:after {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
-ms-transform: rotate(60deg);
-o-transform: rotate(60deg);
}
div:nth-child(2) {
transform: rotate(10deg)
}
div:nth-child(3) {
transform: rotate(20deg)
}
<div></div>
<div></div>
<div></div>
48点爆发
div {
background: red;
width: 80px;
height: 80px;
position: absolute;
text-align: center;
top: 20px;
left: 20px;
}
div:before,
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
height: 80px;
width: 80px;
background: red;
}
div:before {
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
}
div:after {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
-ms-transform: rotate(60deg);
-o-transform: rotate(60deg);
}
div:nth-child(2) {
transform: rotate(7.5deg)
}
div:nth-child(3) {
transform: rotate(15deg)
}
div:nth-child(4) {
transform: rotate(22.5deg)
}
<div></div>
<div></div>
<div></div>
<div></div>
对于超过 12 点的任何内容,我不得不认真地建议使用图像或 SVG,因为上面的答案显示只需要一个元素。
SVG
我用了一个尖刺状的形状(红色形状)
将它放在 defs 中,这样它就不会显示了。
然后多次重复使用尖峰形状并旋转它,其旋转原点设置在形状的最底部。
然后创建一个带有锐边的圆形形状。
.POW {
width: 250px;
height: 250px;
border: 1px solid black;
}
<svg class="POW" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<polygon id="spike" points="0,0, -10,-25 0,-50 10,-25"></polygon>
</defs>
<g class="spikes">
<use x="50" y="50" xlink:href="#spike" transform="rotate(20 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(40 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(60 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(80 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(100 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(120 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(140 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(160 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(180 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(200 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(220 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(240 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(260 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(280 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(300 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(320 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(340 50 50)" />
<use x="50" y="50" fill="red" xlink:href="#spike" transform="rotate(360 50 50)" />
</g>
</svg>
您可以使用此解决方案轻松创建任意数量的尖峰。
只要对旋转进行适当的划分即可:
24点
.POW {
width: 250px;
height: 250px;
border: 1px solid black;
}
<svg class="POW" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<polygon id="spike" points="0,0, -10,-25 0,-50 10,-25"></polygon>
</defs>
<g class="spikes">
<use x="50" y="50" xlink:href="#spike" transform="rotate(0 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(15 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(30 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(45 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(60 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(75 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(90 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(105 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(120 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(135 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(150 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(165 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(180 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(195 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(210 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(225 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(240 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(240 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(255 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(270 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(285 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(300 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(315 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(330 50 50)" />
<use x="50" y="50" fill="red" xlink:href="#spike" transform="rotate(345 50 50)" />
</g>
</svg>
48分
.POW {
width: 250px;
height: 250px;
border: 1px solid black;
}
<svg class="POW" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<polygon id="spike" points="0,0, -10,-25 0,-50 10,-25"></polygon>
</defs>
<g class="spikes">
<use x="50" y="50" xlink:href="#spike" transform="rotate(7.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(15 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(22.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(30 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(37.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(45 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(52.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(60 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(67.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(75 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(82.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(90 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(97.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(105 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(112.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(120 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(127.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(135 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(142.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(150 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(157.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(165 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(172.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(180 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(187.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(195 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(202.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(210 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(217.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(225 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(232.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(240 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(247.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(255 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(262.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(270 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(277.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(285 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(292.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(300 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(307.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(315 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(322.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(330 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(337.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(345 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(352.5 50 50)" />
<use x="50" y="50" fill="red" xlink:href="#spike" transform="rotate(360 50 50)" />
</g>
</svg>
计算角度的方法是将点除以360。
比如:360/48 = 7.5 所以每个角度都需要是 7.5。
- 7.5
- 15.0
- 22.5
- 30
- 37.5
等等
Canvas方法
您也可以使用 Canvas 实现此目的。在 Canvas 上绘图的命令与在 SVG 中几乎相同。在非常高的层次上,该方法是在两个圆上找到点(一个半径为 x,另一个半径稍小),然后将它们连接在一起形成一条路径。当路径被填充时,它给出了一个n点爆发的外观。
在下图中,绿色圆圈是半径为x的大圆圈,蓝色圆圈是较小的内圆圈。通过在圆圈上绘制点并连接它们(使用 lineTo
命令),我们得到了红色的路径。当这条路径被填满时,我们得到了爆裂的外观。 (注:内圈和外圈仅作示意,实际图中未画)
计算逻辑
- 圆上每个点的X和Y坐标可以用下面的公式计算:
- x =(圆的半径 * Cos(以弧度为单位的角度))+ x 中心坐标
- y =(圆的半径 * Sin(以弧度为单位的角度))+ y 中心坐标
- 使用以下逻辑确定在圆上绘制点的 角度:
- 正如您和 Persijn 的回答中所使用的那样,角度计算为(360/爆发次数)。使用360是因为它是一个圆内的总角度。
- 内圆上的点的角度应该在较大圆上的点 1 和点 2 之间的一半,因此会添加一个增量。增量是(360/突发次数)
的一半
- 弧度角度 = 角度角度 * π / 180
window.onload = function() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var defaultBurst = 18;
var defaultContent = "New";
function paint(numBurst, text) {
if (!numBurst) numBurst = defaultBurst;
if (!text) text = defaultContent;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'crimson';
var angleInRad = Math.PI * (360 / numBurst) / 180;
var deltaAngleInRad = angleInRad / 2;
ctx.beginPath();
ctx.moveTo(75, 150);
for (i = 0; i <= numBurst; i++) {
x1 = 75 * Math.cos(angleInRad * i) + 150;
y1 = 75 * Math.sin(angleInRad * i) + 150;
x2 = 60 * Math.cos((angleInRad * i) + deltaAngleInRad) + 150;
y2 = 60 * Math.sin((angleInRad * i) + deltaAngleInRad) + 150;
ctx.lineTo(x1, y1);
ctx.lineTo(x2, y2);
}
ctx.closePath();
/* Add shadow only for shape */
ctx.shadowOffsetX = -5;
ctx.shadowOffsetY = 5;
ctx.shadowBlur = 5;
ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
ctx.fill();
ctx.font = "32px Arial";
ctx.textAlign = "center";
ctx.fillStyle = "gold";
/* Nullify shadow for text */
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.fillText(text, 150, 160, 120);
}
paint();
var slider = document.getElementById('burst');
var textInput = document.getElementById('content');
slider.addEventListener('change', function() {
paint(this.value, textInput.value);
});
textInput.addEventListener('blur', function() {
paint(slider.value, this.value);
});
}
/* For demo only */
.controls {
float: right;
padding: 5px;
margin: 50px 20px;
line-height: 25px;
border: 1px solid;
box-shadow: 1px 1px 0px #222;
}
label,
input {
display: inline-block;
vertical-align: middle;
text-align: left;
}
h3 {
padding: 10px;
text-align: center;
}
label {
width: 100px;
}
input[type='range'],
input[type='text'] {
width: 100px;
}
body {
font-family: Calibri;
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<canvas id='canvas' height='300px' width='300px'></canvas>
<div class='controls'>
<h3>Controls</h3>
<label for="burst">Change Burst:</label>
<input id="burst" class="slider" type="range" value="18" min="12" max="36" step='2' title="Adjust slider to increase or decrease burst" />
<br/>
<label for="content">Text Content:</label>
<input type="text" id="content" maxlength="5" />
</div>
高级演示
查看此 CodePen 高级演示,其中包含路径创建动画、阴影、控制所有功能等功能
使用建议
如果您想要在页面中的某处使用固定大小的图像,那么 Canvas 与 SVG 一样好。但是,如果您需要可以缩放到任意大小的图像,Canvas 不是正确的选择,因为 Canvas 是基于光栅的,缩放时会变得像素化或模糊。
如果您的形状需要动态数量的突发 and/or 文本,Canvas 比 SVG 和 CSS 更可取,因为您不必执行任何 DOM 操作。
我正在尝试制作如下图所示的点爆:
目前,我已经尝试使用伪元素进行此操作,但是,我只能生成 12 点连拍,并且无法反映图像中显示的内容。
有没有办法只用几个元素来创建点爆发?
下面是我用来尝试此解决方案的代码:
div{
width:100px;
height:100px;
background:grey;
transform:rotate(45deg);
margin:50px;
}
div:after{
position:absolute;
content:"";
background:grey;
width:100px;
height:100px;
transform:rotate(135deg);
}
div:before{
position:absolute;
content:"";
background:grey;
width:100px;
height:100px;
transform:rotate(250deg);
}
<div></div>
使用 svg 可以用一个简单的循环。我正在使用 Snap,因为它很简单。
首先使用 snap 创建一个圆,然后使用循环从我引用的圆中找到我们需要的点 this question 以查找点。找到这些点后,简单地给出这些线 points.By 改变循环中的数字,可以创建任何值的弧度值点
24点爆
var s=Snap('svg');
var circle=s.circle(50,50,30).attr({
fill:'tomato',
stroke:'tomato'
})
for (var num = 0; num < 24; num++) {
var rad1 = num * 15 * (Math.PI / 180);
var rad2 = (num+1) * 15 * (Math.PI / 180);
var rad3=(num+.5) * 15 * (Math.PI / 180);
var x1 = (30 * (Math.cos(rad1)) + 50)
var y1 = (30 * (Math.sin(rad1)) + 50)
var x2 = (40 * (Math.cos(rad3)) + 50)
var y2 = (40 * (Math.sin(rad3)) + 50)
var x3 = (30 * (Math.cos(rad2)) + 50)
var y3 = (30 * (Math.sin(rad2)) + 50)
var line=s.polyline(x1,y1,x2,y2,x3,y3).attr({
'fill':'tomato'
})
}
var text=s.text(35,50,'New').attr({
fill:'white'
})
div{
width:100vw;
height:100vh;
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div>
<svg width="100%" height="100%" viewbox="0 0 100 100">
</svg>
</div>
36点爆
var s=Snap('svg');
var circle=s.circle(50,50,30).attr({
fill:'tomato',
stroke:'tomato'
})
for (var num = 0; num < 36; num++) {
var rad1 = num * 10 * (Math.PI / 180);
var rad2 = (num+1) * 10 * (Math.PI / 180);
var rad3=(num+.5) * 10 * (Math.PI / 180);
var x1 = (30 * (Math.cos(rad1)) + 50)
var y1 = (30 * (Math.sin(rad1)) + 50)
var x2 = (40 * (Math.cos(rad3)) + 50)
var y2 = (40 * (Math.sin(rad3)) + 50)
var x3 = (30 * (Math.cos(rad2)) + 50)
var y3 = (30 * (Math.sin(rad2)) + 50)
var line=s.polyline(x1,y1,x2,y2,x3,y3).attr({
'fill':'tomato'
})
}
var text=s.text(35,50,'New').attr({
fill:'white'
})
div{
width:100vw;
height:100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div>
<svg width="100%" height="100%" viewbox="0 0 100 100">
</svg>
</div>
60点爆
var s=Snap('svg');
var circle=s.circle(50,50,30).attr({
fill:'tomato',
stroke:'tomato'
})
for (var num = 0; num < 60; num++) {
var rad1 = num * 6 * (Math.PI / 180);
var rad2 = (num+1) * 6 * (Math.PI / 180);
var rad3=(num+.5) * 6 * (Math.PI / 180);
var x1 = (30 * (Math.cos(rad1)) + 50)
var y1 = (30 * (Math.sin(rad1)) + 50)
var x2 = (40 * (Math.cos(rad3)) + 50)
var y2 = (40 * (Math.sin(rad3)) + 50)
var x3 = (30 * (Math.cos(rad2)) + 50)
var y3 = (30 * (Math.sin(rad2)) + 50)
var line=s.polyline(x1,y1,x2,y2,x3,y3).attr({
'fill':'tomato'
})
}
var text=s.text(35,50,'New').attr({
fill:'white'
})
div{
width:100vw;
height:100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div>
<svg width="100%" height="100%" viewbox="0 0 100 100">
</svg>
</div>
这也可以是动画的
var s=Snap('svg');
var circle=s.circle(50,50,30).attr({
fill:'tomato',
stroke:'tomato'
})
var g=s.g();
for (var num = 0; num < 60; num++) {
var rad1 = num * 6 * (Math.PI / 180);
var rad2 = (num+1) * 6 * (Math.PI / 180);
var rad3=(num+.5) * 6 * (Math.PI / 180);
var x1 = (30 * (Math.cos(rad1)) + 50)
var y1 = (30 * (Math.sin(rad1)) + 50)
var x2 = (40 * (Math.cos(rad3)) + 50)
var y2 = (40 * (Math.sin(rad3)) + 50)
var x3 = (30 * (Math.cos(rad2)) + 50)
var y3 = (30 * (Math.sin(rad2)) + 50)
var line=s.polyline(x1,y1,x2,y2,x3,y3).attr({
'fill':'tomato'
})
g.add(line);
}
var text=s.text(35,50,'New').attr({
fill:'white'
})
function anim(){
g.animate({
transform:'rotate(360 50,50)'
},8000,function(){
g.animate({
transform:'rotate(0 50,50)'
},0,function(){
anim()
})
})
}
anim()
div{
width:100vw;
height:100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div>
<svg width="100%" height="100%" viewbox="0 0 100 100">
</svg>
</div>
请注意,我使用了 vw
和 vh
单位来响应
这也可以用单个折线元素来制作
var s=Snap('svg');
var array=[];
for (var num = 0; num < 24; num++) {
var rad1 = num * 15 * (Math.PI / 180);
var rad2 = (num+1) * 15 * (Math.PI / 180);
var rad3=(num+.5) * 15 * (Math.PI / 180);
var x1 = (30 * (Math.cos(rad1)) + 50);
var y1 = (30 * (Math.sin(rad1)) + 50);
var x2 = (40 * (Math.cos(rad3)) + 50);
var y2 = (40 * (Math.sin(rad3)) + 50);
var x3 = (30 * (Math.cos(rad2)) + 50);
var y3 = (30 * (Math.sin(rad2)) + 50);
array.push(x1+','+y1+' '+x2+','+y2+' '+x3+','+' '+y3);
}
var line=s.polyline(array).attr({
'fill':'tomato'
})
var text=s.text(35,50,'New').attr({
fill:'white'
})
div{
width:100vw;
height:100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div>
<svg width="100%" height="100%" viewbox="0 0 100 100">
</svg>
</div>
这可以用 CSS 但在 12 点之后,需要不止一个 div。
我之前曾在项目中使用 12 点爆发作为提醒和促销风格元素。
12 点爆发
div {
background: red;
width: 80px;
height: 80px;
position: absolute;
text-align: center;
top: 20px;
left: 20px;
}
div:before,
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
height: 80px;
width: 80px;
background: red;
}
div:before {
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
}
div:after {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
-ms-transform: rotate(60deg);
-o-transform: rotate(60deg);
}
<div></div>
24点爆发
div {
background: red;
width: 80px;
height: 80px;
position: absolute;
text-align: center;
top: 20px;
left: 20px;
}
div:before, div:after {
content: "";
position: absolute;
top: 0;
left: 0;
height: 80px;
width: 80px;
background: red;
}
div:before {
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
}
div:after {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
-ms-transform: rotate(60deg);
-o-transform: rotate(60deg);
}
div:nth-child(2) {
transform: rotate(15deg)
}
<div></div>
<div></div>
36点爆发
div {
background: red;
width: 80px;
height: 80px;
position: absolute;
text-align: center;
top: 20px;
left: 20px;
}
div:before, div:after {
content: "";
position: absolute;
top: 0;
left: 0;
height: 80px;
width: 80px;
background: red;
}
div:before {
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
}
div:after {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
-ms-transform: rotate(60deg);
-o-transform: rotate(60deg);
}
div:nth-child(2) {
transform: rotate(10deg)
}
div:nth-child(3) {
transform: rotate(20deg)
}
<div></div>
<div></div>
<div></div>
48点爆发
div {
background: red;
width: 80px;
height: 80px;
position: absolute;
text-align: center;
top: 20px;
left: 20px;
}
div:before,
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
height: 80px;
width: 80px;
background: red;
}
div:before {
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
}
div:after {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
-ms-transform: rotate(60deg);
-o-transform: rotate(60deg);
}
div:nth-child(2) {
transform: rotate(7.5deg)
}
div:nth-child(3) {
transform: rotate(15deg)
}
div:nth-child(4) {
transform: rotate(22.5deg)
}
<div></div>
<div></div>
<div></div>
<div></div>
对于超过 12 点的任何内容,我不得不认真地建议使用图像或 SVG,因为上面的答案显示只需要一个元素。
SVG
我用了一个尖刺状的形状(红色形状)
将它放在 defs 中,这样它就不会显示了。
然后多次重复使用尖峰形状并旋转它,其旋转原点设置在形状的最底部。
然后创建一个带有锐边的圆形形状。
.POW {
width: 250px;
height: 250px;
border: 1px solid black;
}
<svg class="POW" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<polygon id="spike" points="0,0, -10,-25 0,-50 10,-25"></polygon>
</defs>
<g class="spikes">
<use x="50" y="50" xlink:href="#spike" transform="rotate(20 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(40 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(60 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(80 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(100 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(120 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(140 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(160 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(180 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(200 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(220 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(240 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(260 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(280 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(300 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(320 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(340 50 50)" />
<use x="50" y="50" fill="red" xlink:href="#spike" transform="rotate(360 50 50)" />
</g>
</svg>
您可以使用此解决方案轻松创建任意数量的尖峰。 只要对旋转进行适当的划分即可:
24点
.POW {
width: 250px;
height: 250px;
border: 1px solid black;
}
<svg class="POW" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<polygon id="spike" points="0,0, -10,-25 0,-50 10,-25"></polygon>
</defs>
<g class="spikes">
<use x="50" y="50" xlink:href="#spike" transform="rotate(0 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(15 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(30 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(45 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(60 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(75 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(90 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(105 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(120 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(135 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(150 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(165 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(180 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(195 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(210 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(225 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(240 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(240 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(255 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(270 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(285 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(300 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(315 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(330 50 50)" />
<use x="50" y="50" fill="red" xlink:href="#spike" transform="rotate(345 50 50)" />
</g>
</svg>
48分
.POW {
width: 250px;
height: 250px;
border: 1px solid black;
}
<svg class="POW" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<polygon id="spike" points="0,0, -10,-25 0,-50 10,-25"></polygon>
</defs>
<g class="spikes">
<use x="50" y="50" xlink:href="#spike" transform="rotate(7.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(15 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(22.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(30 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(37.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(45 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(52.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(60 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(67.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(75 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(82.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(90 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(97.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(105 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(112.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(120 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(127.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(135 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(142.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(150 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(157.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(165 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(172.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(180 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(187.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(195 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(202.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(210 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(217.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(225 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(232.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(240 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(247.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(255 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(262.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(270 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(277.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(285 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(292.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(300 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(307.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(315 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(322.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(330 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(337.5 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(345 50 50)" />
<use x="50" y="50" xlink:href="#spike" transform="rotate(352.5 50 50)" />
<use x="50" y="50" fill="red" xlink:href="#spike" transform="rotate(360 50 50)" />
</g>
</svg>
计算角度的方法是将点除以360。
比如:360/48 = 7.5 所以每个角度都需要是 7.5。
- 7.5
- 15.0
- 22.5
- 30
- 37.5
等等
Canvas方法
您也可以使用 Canvas 实现此目的。在 Canvas 上绘图的命令与在 SVG 中几乎相同。在非常高的层次上,该方法是在两个圆上找到点(一个半径为 x,另一个半径稍小),然后将它们连接在一起形成一条路径。当路径被填充时,它给出了一个n点爆发的外观。
在下图中,绿色圆圈是半径为x的大圆圈,蓝色圆圈是较小的内圆圈。通过在圆圈上绘制点并连接它们(使用 lineTo
命令),我们得到了红色的路径。当这条路径被填满时,我们得到了爆裂的外观。 (注:内圈和外圈仅作示意,实际图中未画)
计算逻辑
- 圆上每个点的X和Y坐标可以用下面的公式计算:
- x =(圆的半径 * Cos(以弧度为单位的角度))+ x 中心坐标
- y =(圆的半径 * Sin(以弧度为单位的角度))+ y 中心坐标
- 使用以下逻辑确定在圆上绘制点的 角度:
- 正如您和 Persijn 的回答中所使用的那样,角度计算为(360/爆发次数)。使用360是因为它是一个圆内的总角度。
- 内圆上的点的角度应该在较大圆上的点 1 和点 2 之间的一半,因此会添加一个增量。增量是(360/突发次数) 的一半
- 弧度角度 = 角度角度 * π / 180
window.onload = function() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var defaultBurst = 18;
var defaultContent = "New";
function paint(numBurst, text) {
if (!numBurst) numBurst = defaultBurst;
if (!text) text = defaultContent;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'crimson';
var angleInRad = Math.PI * (360 / numBurst) / 180;
var deltaAngleInRad = angleInRad / 2;
ctx.beginPath();
ctx.moveTo(75, 150);
for (i = 0; i <= numBurst; i++) {
x1 = 75 * Math.cos(angleInRad * i) + 150;
y1 = 75 * Math.sin(angleInRad * i) + 150;
x2 = 60 * Math.cos((angleInRad * i) + deltaAngleInRad) + 150;
y2 = 60 * Math.sin((angleInRad * i) + deltaAngleInRad) + 150;
ctx.lineTo(x1, y1);
ctx.lineTo(x2, y2);
}
ctx.closePath();
/* Add shadow only for shape */
ctx.shadowOffsetX = -5;
ctx.shadowOffsetY = 5;
ctx.shadowBlur = 5;
ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
ctx.fill();
ctx.font = "32px Arial";
ctx.textAlign = "center";
ctx.fillStyle = "gold";
/* Nullify shadow for text */
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.fillText(text, 150, 160, 120);
}
paint();
var slider = document.getElementById('burst');
var textInput = document.getElementById('content');
slider.addEventListener('change', function() {
paint(this.value, textInput.value);
});
textInput.addEventListener('blur', function() {
paint(slider.value, this.value);
});
}
/* For demo only */
.controls {
float: right;
padding: 5px;
margin: 50px 20px;
line-height: 25px;
border: 1px solid;
box-shadow: 1px 1px 0px #222;
}
label,
input {
display: inline-block;
vertical-align: middle;
text-align: left;
}
h3 {
padding: 10px;
text-align: center;
}
label {
width: 100px;
}
input[type='range'],
input[type='text'] {
width: 100px;
}
body {
font-family: Calibri;
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<canvas id='canvas' height='300px' width='300px'></canvas>
<div class='controls'>
<h3>Controls</h3>
<label for="burst">Change Burst:</label>
<input id="burst" class="slider" type="range" value="18" min="12" max="36" step='2' title="Adjust slider to increase or decrease burst" />
<br/>
<label for="content">Text Content:</label>
<input type="text" id="content" maxlength="5" />
</div>
高级演示
查看此 CodePen 高级演示,其中包含路径创建动画、阴影、控制所有功能等功能
使用建议
如果您想要在页面中的某处使用固定大小的图像,那么 Canvas 与 SVG 一样好。但是,如果您需要可以缩放到任意大小的图像,Canvas 不是正确的选择,因为 Canvas 是基于光栅的,缩放时会变得像素化或模糊。
如果您的形状需要动态数量的突发 and/or 文本,Canvas 比 SVG 和 CSS 更可取,因为您不必执行任何 DOM 操作。