gpt4 book ai didi

javascript - 德国风格的铁路时钟。 SVG 的可怕使用?

转载 作者:行者123 更新时间:2023-11-29 10:38:37 26 4
gpt4 key购买 nike

别笑,我对 SVG 的了解几乎。这是我第一次尝试动画 svg 阴影。我想要的只是动态访问过滤器 feOffset 的 dx 和 dy 属性,以便在时钟指针围绕表盘移动时提供逼真的阴影位置。我能做到的唯一方法是拆开 svg 并用 JavaScript 重新组装它。它工作正常,在我的机器上以大约 1.5% 到 4% 的 cpu 运行,setTimeout 周期约为 30mls(需要平稳的二手)。我丢弃了 requestanimationframe,因为长时间没有页面焦点,时间会花掉。就目前而言,脚本在每个新周期中创建/替换(我认为!)新 svg。无论如何,我的问题是有更好/正确的方法来访问和操作 dx 和 dy 吗?Ps:我只使用 svg,因为我想要的形状显然不能用 css 生成,而且时钟是完全可调整大小的,图像 png 等是 Not Acceptable 。感谢您的帮助。

(function () {

/* German Station Style Clock */


/* ^^^^^^^^^^^^ Config below ^^^^^^^^^^^^ */

var clockSize = 500;
var casecol = 'rgba(40,40,40,1.0)';
var dialcol = 'rgba(255,255,255,1.0)';
var numcol = 'rgba(40,40,40,1.0)';
var seccol = 'rgba(200,0,0,1.0)';
var handcol = 'rgba(40,40,40,1.0)';
var shadowOpacity = 0.3;
var shadowBlur = 0.2;
var shadowAngle = 0.6;
var clockShape = 50;
/* (max) 50 = round (min) 0 = square */
var numoutline = 'no';
/* 'yes' or 'no' */
var numfill = 'rgba(255,0,0,1.0)';
var numshad = 'rgba(0,0,0,0.1)';

/* ^^^^^^^^^^^^^ End config ^^^^^^^^^^^^^ */

var d = document;
var dgts = [];
var e = 360/12;
var degr = 0;
var nums = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'];
var tmr;
var mls = 1000 / 30;
var radi = Math.PI / 180;
var offs = 60 * radi;
var canstroke = ('webkitTextStroke' in d.body.style);
var str = '-webkit-text-fill-color: '+numfill+';'
+'-webkit-text-stroke-width: '+xy(0.4)+'px;'
+'-webkit-text-stroke-color: '+numcol+';';
var wks = (canstroke && numoutline == "yes")?str:'';
var broff = (clockShape < 20)?2:0;
var presec;
var premin;
var prehou;
var rnd = 'id'+Math.random() * 1;
var idx = d.getElementsByTagName('div').length;
d.write('<div id = "'+rnd+'" style="display:inline-block;line-height:0px;"></div>');

function xy (a) {
return (a * clockSize / 100);
}

/* Clock dial */
var dial = d.createElement('div');
dial.setAttribute('style', 'display:inline-block;'
+'position: relative;'
+'height: '+clockSize+'px;'
+'width: '+clockSize+'px;'
+'background-color: '+dialcol+';'
+'border: '+xy(2)+'px solid '+casecol+';'
+'border-radius: '+clockShape+'%;');
d.getElementById(rnd).appendChild(dial);

/* Clock markers */
for (var i = 0; i < 12; i++) {
dgts[i] = d.createElement('div');
dgts[i].setAttribute('style', 'display: block;'
+'position: absolute;'
+'width: '+xy(16)+'px;'
+'height: '+xy(14)+'px;'
+'margin: auto;top: 0;bottom: 0; left: 0;right: 0;'
+'font: bold '+xy(13)+'px Arial;'
+'line-height: '+xy(13)+'px;'
+'text-align: center !important;'
+'color: '+numcol+';'+wks+';');
dgts[i].innerHTML = nums[i];
dial.appendChild(dgts[i]);
degr += 30;
dgts[i].style.top = xy(0) + xy(84) * Math.sin(-offs + e * i * radi) + 'px';
dgts[i].style.left= xy(0) + xy(84) * Math.cos(-offs + e * i * radi) + 'px';
dgts[i].style.transform = 'rotate(' + (degr) + 'deg)';
dgts[i].style.transformOrigin = 'center center';
}

/* Generic container div for all hands */
var handContainers = 'display: block;'
+'position: absolute;'
+'height: '+xy(100)+'px;'
+'width: '+xy(20)+'px;'
+'font-size: 0px; line-height: 0px; padding: 0;'
+'margin: auto; top: 0;bottom: 0; left: 0; right: 0;'
+'transform-origin: center center;'

/* Hour hand */
var houHand = d.createElement('div');
houHand.setAttribute('style', handContainers + 'transition: .5s cubic-bezier(0.666, 1.91, 0.333, 0);');
dial.appendChild(houHand);
var houC = d.createElement('div');
var housvg = '<polygon points="94,46 100,40 106,46 106,118 94,118" style="fill:'+handcol+'; stroke:none"/>';

/* Minute hand */
var minHand = d.createElement('div');
minHand.setAttribute('style',handContainers + 'transition: .4s cubic-bezier(0.666, 1.91, 0.333, 0);');
dial.appendChild(minHand);
var minC = d.createElement('div');
var minsvg = '<polygon points="95.5,11.5 100,7 104.5,11.5 104.5,122 95.5,122" style="fill:'+handcol+'; stroke:none"/>';

/* Seconds hand */
var secHand = d.createElement('div');
secHand.setAttribute('style',handContainers);
dial.appendChild(secHand);
var secC = d.createElement('div');
var secsvg = '<polygon points="98.8,11 100,9.8 101.2,11 101.6,42 98.4,42" style="fill:'+seccol+'; stroke:none"/>'+
'<polygon points="98.1,58 101.9,58 102.5,122 97.5,122" style="fill:'+seccol+'; stroke:none"/>'+
'<circle cx="100" cy="50" r="8.5" style="fill:none; stroke:'+seccol+'; stroke-width:6.5"/>';

function dropShadow(s, h) {
var depth = xy(h);
var angle = s * radi - shadowAngle;
var vsa = depth * Math.cos(angle);
var hsa = depth * Math.sin(angle);
return {vsa:vsa, hsa:hsa}
}

var str1 = '<svg height="'+xy(100)+'" width="'+xy(20)+'" viewBox="90.25 -4 20 200" ><defs>';
var str3 = '<feGaussianBlur in="SourceAlpha" stdDeviation="'+shadowBlur+'"/>';
var str5 = '<feFlood flood-color="#000000" flood-opacity="'+shadowOpacity+'"/>'+
'<feComposite in2="offsetblur" operator="in"/>'+
'<feMerge>'+
'<feMergeNode/>'+
'<feMergeNode in="SourceGraphic"/>'+
'</feMerge>'+
'</filter>'+
'</defs>';
var str8 = '</g></svg>';

function dynShad (str2, str4, str6, str7) {
var create = str1 + str2 + str3 + str4 + str5 + str6 + str7 + str8;
return create;
}

function clock() {
var x = new Date();

var time = Math.min(60000, 1.025 * (1000 * x.getSeconds() + x.getMilliseconds()));
var seconds = Math.floor(time / 1000);
var millis = time % 1000;
var germanSec = (6 * seconds + 3 * (1 + Math.cos(Math.PI + Math.PI * (0.001 * millis))));
var minutes = x.getMinutes();
var hours = (x.getHours() * 30) + (minutes / 2);



if (germanSec !== presec) {
var ssy = dropShadow(germanSec, 0.7).vsa;
var ssx = dropShadow(germanSec, 0.7).hsa;
var sf = '<filter id="sf'+idx+'" x="-50%" y="-50%" width="200%" height="200%">';
var se = '<g filter="url(#sf'+idx+')">';
var ss = '<feOffset id="soffset'+idx+'" dx="'+ssx+'" dy="'+ssy+'" result="offsetblur"/>';
secC.innerHTML = dynShad (sf, ss,se, secsvg);
secHand.appendChild(secC);
}

if (minutes !== premin) {
var msy = dropShadow(minutes * 6, 0.5).vsa;
var msx = dropShadow(minutes * 6, 0.5).hsa;
var mf = '<filter id="mf'+idx+'" x="-50%" y="-50%" width="200%" height="200%">';
var me ='<g filter="url(#mf'+idx+')">';
var ms = '<feOffset id="moffset'+idx+'" dx="'+msx+'" dy="'+msy+'" result="offsetblur"/>';
minC.innerHTML = dynShad (mf, ms,me, minsvg);
minHand.appendChild(minC);
}

if (hours !== prehou) {
var hsy = dropShadow(hours, 0.4).vsa;
var hsx = dropShadow(hours, 0.4).hsa;
var hf = '<filter id="hf'+idx+'" x="-50%" y="-50%" width="200%" height="200%">';
var he ='<g filter="url(#hf'+idx+')">';
var hs = '<feOffset id="hoffset'+idx+'" dx="'+hsx+'" dy="'+hsy+'" result="offsetblur"/>';
houC.innerHTML = dynShad (hf, hs,he, housvg);
houHand.appendChild(houC);
}

secHand.style.transform = 'rotate(' + germanSec + 'deg) translateZ(0)';
minHand.style.transform = 'rotate(' + (minutes * 6) + 'deg) translateZ(0)';
houHand.style.transform = 'rotate(' + hours + 'deg) translateZ(0)';

presec = germanSec;
premin = minutes;
prehou = hours;

tmr = setTimeout(clock, mls);
}

window.addEventListener('load', clock, false);
})();

最佳答案

All I wanted was to dynamically access the filter feOffset's dx and dy attributes to give the clock hands realistic shadow positions as they move around the dial.

实际上,您不必为了逼真的阴影而触及 dx 和 dy 属性。您所要做的就是将手放在 g 元素上并将阴影应用于组(不旋转)。在这种情况下,阴影不会旋转,因此偏移量保持不变。

看这个例子,矩形在旋转,但是阴影被应用到组中:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="200" height="200">
<defs>
<filter id="gb" filterUnits="userSpaceOnUse" x="-50" y="-50" width="100" height="100">
<feGaussianBlur in="SourceAlpha" stdDeviation="1" />
<feOffset dx="2" dy="2" />
<feMerge>
<feMergeNode />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<g transform="translate(50 50)" filter="url(#gb)">
<rect x="-0.5" y="-45" width="1" height="45" fill="red">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="10s" repeatCount="indefinite"/>
</rect>
</g>
</svg>

var r=document.getElementById("rect")

setInterval(function(){
var d = new Date();
var a = d.getSeconds()*6; // 360/60 so every second equals 6 deg
r.setAttribute("transform","rotate("+a+")");
},500);
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="200" height="200">
<defs>
<filter id="gb" filterUnits="userSpaceOnUse" x="-50" y="-50" width="100" height="100">
<feGaussianBlur in="SourceAlpha" stdDeviation="1" />
<feOffset dx="2" dy="2" />
<feMerge>
<feMergeNode />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<g transform="translate(50 50)" filter="url(#gb)">
<rect id="rect" x="-0.5" y="-45" width="1" height="45" fill="red"/>
</g>
</svg>

关于javascript - 德国风格的铁路时钟。 SVG 的可怕使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32810205/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com