我已经使用实验性的@property特性成功地创建了一个css变量动画。
重要事项:这仅适用于Chrome、Opera或边缘兼容性表
document.addEventListener('DOMContentLoaded', () => {
const rangeInput = document.querySelector('#scale');
const htmlElement = document.querySelector('#html-element');
rangeInput.addEventListener('change', (e) => {
htmlElement.style.setProperty(
'--html-element-scale',
(e.target.value / 100).toFixed(2)
);
});
});@property --html-element-background-color {
syntax: '<color>';
inherits: false;
initial-value: #00ff00;
}
@property --html-element-rotate {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
@property --html-element-scale {
syntax: '<number>';
inherits: false;
initial-value: 1;
}
#html-element {
transform: rotate(var(--html-element-rotate))
scale(var(--html-element-scale));
border: 1px solid #000;
height: 100px;
width: 100px;
background-color: var(--html-element-background-color);
animation: anim 1s ease-in infinite alternate;
}
@keyframes anim {
100% {
--html-element-rotate: 180deg;
--html-element-background-color: #ff00ff;
}
}<div id="html-element">HTML Element</div>
<div id="range-container">
<input
type="range"
id="scale"
name="scale"
min="0"
max="100"
value="100"
/>
<label for="scale">Scale</label>
</div>
但是当将它包装到web组件中时,只有css值会被更改,但是css var的值不会被动画化。此外,旋转不起作用,除非您更改缩放滑块或将:host {--html-element-scale: 1}作为默认值.这很奇怪。
const html = `
<style>
@property --web-component-background-color {
syntax: '<color>';
inherits: false;
initial-value: #00ff00;
}
@property --web-component-rotate {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
@property --web-component-scale {
syntax: '<number>';
inherits: false;
initial-value: 1;
}
#web-component {
transform: scale(var(--web-component-scale)) rotate(var(--web-component-rotate));
border: 1px solid #000;
height: 100px;
width: 100px;
background-color: var(--web-component-background-color);
animation: anim 1s ease-in infinite alternate;
}
@keyframes anim {
100% {
--web-component-rotate: 180deg;
--web-component-background-color: #ff00ff;
}
}
</style>
<div id="web-component">Web Component</div>
<div id="range-container">
<input type="range" id="scale" name="scale" min="0" max="100" value="100" />
<label for="scale">Scale</label>
</div>`;
customElements.define(
'web-component',
class WebComponent extends HTMLElement {
shadowRoot = this.attachShadow({ mode: 'open' });
constructor() {
super();
let template = document.createElement('template');
template.innerHTML = html;
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
connectedCallback() {
const rangeInput = this.shadowRoot.querySelector('#scale');
const webComponent = this.shadowRoot.querySelector('#web-component');
rangeInput.addEventListener('change', (e) => {
webComponent.style.setProperty(
'--web-component-scale',
(e.target.value / 100).toFixed(2)
);
});
}
}
);<web-component></web-component>
最后但并非最不重要的一点是,如果您将样式表从web组件复制到常规的dom中,那么web组件继承了css,它将再次工作。
问题是,这是由于该特性的实验阶段造成的错误,还是我在web组件中实现它时做错了什么?
发布于 2022-06-21 21:29:30
看起来,@property定义在web组件中不起作用。我不确定这是有意还是错误,我会把它作为一个问题向项目报告。
但是,如果您只想在动画中使用全局定义的css变量(这在web组件的用例中是非常有限的),那么如果您对工作版本感兴趣的话。
const html = `
<style>
#web-component {
transform: rotate(var(--html-element-rotate))
scale(var(--html-element-scale));
border: 1px solid #000;
height: 100px;
width: 100px;
background-color: var(--html-element-background-color);
animation: anim 1s ease-in infinite alternate;
}
@keyframes anim {
100% {
--html-element-rotate: -180deg;
--html-element-background-color: #0000ff;
}
}
</style>
<div id="web-component">Web Component</div>
<div id="range-container">
<input type="range" id="scale" name="scale" min="0" max="100" value="100" />
<label for="scale">Scale</label>
</div>`;
document.addEventListener('DOMContentLoaded', () => {
const rangeInput = document.querySelector('#scale');
const htmlElement = document.querySelector('#html-element');
rangeInput.addEventListener('change', (e) => {
htmlElement.style.setProperty(
'--html-element-scale',
(e.target.value / 100).toFixed(2)
);
});
});
customElements.define(
'web-component',
class WebComponent extends HTMLElement {
shadowRoot = this.attachShadow({ mode: 'open' });
constructor() {
super();
let template = document.createElement('template');
template.innerHTML = html;
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
connectedCallback() {
const rangeInput = this.shadowRoot.querySelector('#scale');
const webComponent = this.shadowRoot.querySelector('#web-component');
rangeInput.addEventListener('change', (e) => {
webComponent.style.setProperty(
'--html-element-scale',
(e.target.value / 100).toFixed(2)
);
});
}
}
);@property --html-element-background-color {
syntax: '<color>';
inherits: false;
initial-value: #00ff00;
}
@property --html-element-rotate {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
@property --html-element-scale {
syntax: '<number>';
inherits: false;
initial-value: 1;
}
#html-element {
transform: rotate(var(--html-element-rotate))
scale(var(--html-element-scale));
border: 1px solid #000;
height: 100px;
width: 100px;
background-color: var(--html-element-background-color);
animation: anim 1s ease-in infinite alternate;
}
@keyframes anim {
100% {
--html-element-rotate: 180deg;
--html-element-background-color: #ff00ff;
}
}<web-component></web-component>
<div id="html-element">HTML Element</div>
<div id="range-container">
<input
type="range"
id="scale"
name="scale"
min="0"
max="100"
value="100"
/>
<label for="scale">Scale</label>
</div>
https://stackoverflow.com/questions/72705688
复制相似问题