Javascript 如何在Web组件中展平/消除属性更改回调
我有一个web组件正在使用Javascript 如何在Web组件中展平/消除属性更改回调,javascript,html,web-component,native-web-component,Javascript,Html,Web Component,Native Web Component,我有一个web组件正在使用attributeChangedCallback attributeChangedCallback(name, oldValue, newValue) { // TODO: use something like rxjs debounce time? this.expensiveRenderer() } 我正在为每个动画帧上的两个属性设置新值: 此外,这可以增加到设置4个属性 component.setAttribute("att1", r); com
attributeChangedCallback
attributeChangedCallback(name, oldValue, newValue) {
// TODO: use something like rxjs debounce time?
this.expensiveRenderer()
}
我正在为每个动画帧上的两个属性设置新值:
此外,这可以增加到设置4个属性
component.setAttribute("att1", r);
component.setAttribute("att2", p);
function animateSpirograph(spirograph, r, p, rIncrement, pIncrement) {
let v = r;
if (v + rIncrement > 100) rIncrement = -Math.abs(rIncrement);
if (v + rIncrement <= 0) rIncrement = Math.abs(rIncrement);
v = v + rIncrement;
r = v;
let w = p;
if (w + pIncrement > 200) pIncrement = -Math.abs(pIncrement);
if (w + pIncrement <= 0) pIncrement = Math.abs(pIncrement);
w = w + pIncrement;
p = w;
spirograph.setAttribute("moving-circle-radius", r);
spirograph.setAttribute("moving-circle-locus-length", p);
window.requestAnimationFrame(() =>
animateSpirograph(spirograph, r, p, rIncrement, pIncrement)
);
}
这将触发两次attributeChangedCallback
,并且昂贵的渲染器也会触发两次
有没有一种有效的方法将两个属性设置在一起,或者将更改的效果作为一个类似于去盎司时间的单一事件
我对使用setTimeout
/clearTimeout
有点怀疑,因为它在每个动画帧上调用60 fps
为了提供更好的概述,我的组件看起来有点像:
<mm-spirograph
fixed-circle-radius="100"
moving-circle-radius="10"
moving-circle-locus-length="30"
repeat-count="100"
></mm-spirograph>
它用webGL呈现螺旋图,并计划用于生成艺术。
我喜欢这种简单性,并且有点不愿意使用JSON属性
此外,设置spirograph的动画与组件是分开的,其想法是将spirograph用作静态渲染,或者更改属性可以轻松完成类似动画的操作。在这里,它仅为两个属性设置动画,但在不同情况下可能会有所不同
此外,还计划添加类似的组件,如果需要,可以通过设置属性来设置动画
component.setAttribute("att1", r);
component.setAttribute("att2", p);
function animateSpirograph(spirograph, r, p, rIncrement, pIncrement) {
let v = r;
if (v + rIncrement > 100) rIncrement = -Math.abs(rIncrement);
if (v + rIncrement <= 0) rIncrement = Math.abs(rIncrement);
v = v + rIncrement;
r = v;
let w = p;
if (w + pIncrement > 200) pIncrement = -Math.abs(pIncrement);
if (w + pIncrement <= 0) pIncrement = Math.abs(pIncrement);
w = w + pIncrement;
p = w;
spirograph.setAttribute("moving-circle-radius", r);
spirograph.setAttribute("moving-circle-locus-length", p);
window.requestAnimationFrame(() =>
animateSpirograph(spirograph, r, p, rIncrement, pIncrement)
);
}
函数动画透视图(透视图、r、p、r增量、pIncrement){
设v=r;
如果(v+rIncrement>100)rIncrement=-Math.abs(rIncrement);
如果(v+rIncrement 200)pIncrement=-Math.abs(pIncrement);
if(w+pIncrement)
动画描记器(描记器、r、p、rIncrement、pIncrement)
);
}
Danny的建议很有趣,我可以有第三个属性,它可能是requestAnimationFrame的时间戳,并将其标记为仅用于动画的可选属性。因此,每次更改属性时,我们都需要设置此额外属性以实际触发渲染。但这听起来有点像黑客/补丁。使用超时。这允许在执行昂贵的渲染之前执行整个代码
类MyEl扩展HtmleElement{
构造函数(){
超级();
this.renderTimeout=null;
this.renderCalled=0;
this.renderDone=0;
}
静态get ObservedAttribute(){
返回['time','direction'];
}
费用支付人(){
这个.renderCalled++;
if(this.renderTimeout){
clearTimeout(this.renderTimeout);
}
this.renderTimeout=setTimeout(
() => {
这个.renderDone++;
this.innerHTML=`时间是:${this.\u time}方向是${this.\u direction}渲染调用:${this.renderCalled}渲染:${this.renderDone}`;
}, 1
);
}
attributeChangedCallback(名称、旧值、新值){
如果(旧值!==新值){
这个[`{name}`]=newValue;
这是一个昂贵的价格;
}
}
}
自定义元素。定义('my-el',MyEl);
const component=document.querySelector('my-el');
设置超时(()=>{
setAttribute(“时间”,“1:00”);
setAttribute(“时间”,“2:00”);
setAttribute(“时间”,“3:00”);
setAttribute(“时间”,“4:00”);
setAttribute(“方向”、“东”);
setAttribute(“方向”、“西”);
setAttribute(“方向”、“南”);
}, 2000);代码>
使用超时。这允许在执行昂贵的渲染之前执行整个代码
类MyEl扩展HtmleElement{
构造函数(){
超级();
this.renderTimeout=null;
this.renderCalled=0;
this.renderDone=0;
}
静态get ObservedAttribute(){
返回['time','direction'];
}
费用支付人(){
这个.renderCalled++;
if(this.renderTimeout){
clearTimeout(this.renderTimeout);
}
this.renderTimeout=setTimeout(
() => {
这个.renderDone++;
this.innerHTML=`时间是:${this.\u time}方向是${this.\u direction}渲染调用:${this.renderCalled}渲染:${this.renderDone}`;
}, 1
);
}
attributeChangedCallback(名称、旧值、新值){
如果(旧值!==新值){
这个[`{name}`]=newValue;
这是一个昂贵的价格;
}
}
}
自定义元素。定义('my-el',MyEl);
const component=document.querySelector('my-el');
设置超时(()=>{
setAttribute(“时间”,“1:00”);
setAttribute(“时间”,“2:00”);
setAttribute(“时间”,“3:00”);
setAttribute(“时间”,“4:00”);
setAttribute(“方向”、“东”);
setAttribute(“方向”、“西”);
setAttribute(“方向”、“南”);
}, 2000);代码>
是否需要观察观察到的属性中的所有属性
?它们是什么类型的属性?它们是本机HTML元素属性吗?否则,您可以简单地在一个数据属性中使用带有多个键值对的JSON字符串。或者添加第三个观察到的属性来设置其他两个,或者仅在第二个属性发生更改时触发渲染器。您需要观察观察到的属性中的所有属性吗?它们是什么类型的属性?它们是本机HTML元素属性吗?否则,您可以简单地使用一个JSON字符串,在一个数据属性中包含多个键值对。或者添加第三个观察到的属性,设置其他两个键值对,或者仅在第二个属性发生更改时触发渲染器。这样做的效果也比我预期的好,性能非常出色。很高兴我能提供帮助!哇,这比我预期的要好得多,性能非常出色。很高兴我能帮上忙!