Skip to content

Commit 8c20638

Browse files
authored
0.27.1 (css-doodle#79)
1 parent 456dfb9 commit 8c20638

File tree

4 files changed

+115
-42
lines changed

4 files changed

+115
-42
lines changed

CHANGELOG.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1+
## 0.27.1
2+
3+
* Add `pause/resume` to Shader and CSS animations. (#78)
4+
* Use CSS variable for Shader background value. (#77)
5+
* Clear Shader animations on `update` or `disconnected`. (#76)
6+
7+
<br /> <br />
8+
9+
10+
111
## 0.27.0
212

313
### Features
414

515
* Add `u_time` uniform to `@shaders`. Now it supports animation in shaders. (#70)
6-
* Add support for shader syntax compatibility with shadertoy (#73)
16+
* Add support for shader syntax compatible with shadertoy (#73)
717
* Increase grid size up to `256x256`. (#73)
818

919
### Fixes

css-doodle.js

+100-37
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
22
(function (global, factory) {
33
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
44
typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -3797,6 +3797,7 @@
37973797
compose_shaders(shader, {x, y, z}) {
37983798
let id = unique_id('shader');
37993799
this.shaders[id] = {
3800+
id: '--' + id,
38003801
shader,
38013802
cell: cell_id(x, y, z)
38023803
};
@@ -5056,11 +5057,56 @@ void main() {
50565057
return transform(getComputedStyle(element).color);
50575058
}
50585059

5060+
const STEP60 = 1000 / 60; // 60fps
5061+
const STEP1 = 1000 / 1; // 1fps
5062+
5063+
function createAnimationFrame(fn) {
5064+
let id;
5065+
let time = 0;
5066+
let lastTime = 0;
5067+
let lastStep = 0;
5068+
let paused = false;
5069+
function loop(stamp) {
5070+
if (!time) time = stamp;
5071+
fn(time);
5072+
let step = (stamp - lastTime);
5073+
if (step < STEP60) step = STEP60;
5074+
if (step > STEP1) step = lastStep || STEP1;
5075+
if (lastTime) time += step;
5076+
lastStep = step;
5077+
lastTime = stamp;
5078+
id = requestAnimationFrame(loop);
5079+
}
5080+
id = requestAnimationFrame(loop);
5081+
return {
5082+
resume() {
5083+
if (id && paused) {
5084+
paused = false;
5085+
id = requestAnimationFrame(loop);
5086+
}
5087+
},
5088+
pause() {
5089+
if (id) {
5090+
cancelAnimationFrame(id);
5091+
paused = true;
5092+
}
5093+
},
5094+
cancel() {
5095+
if (id) {
5096+
paused = false;
5097+
cancelAnimationFrame(id);
5098+
id = null;
5099+
}
5100+
},
5101+
}
5102+
}
5103+
50595104
if (typeof customElements !== 'undefined') {
50605105
class Doodle extends HTMLElement {
50615106
constructor() {
50625107
super();
50635108
this.doodle = this.attachShadow({ mode: 'open' });
5109+
this.animations = [];
50645110
this.extra = {
50655111
get_variable: name => get_variable(this, name),
50665112
get_rgba_color: value => get_rgba_color(this.shadowRoot, value),
@@ -5075,8 +5121,17 @@ void main() {
50755121
}
50765122
}
50775123

5078-
update(styles) {
5124+
disconnectedCallback() {
50795125
Cache.clear();
5126+
for (let animation of this.animations) {
5127+
animation.cancel();
5128+
}
5129+
this.animations = [];
5130+
}
5131+
5132+
update(styles) {
5133+
this.disconnectedCallback();
5134+
50805135
let use = this.get_use();
50815136
if (!styles) styles = un_entity(this.innerHTML);
50825137
this.innerHTML = styles;
@@ -5265,32 +5320,44 @@ void main() {
52655320
draw_canvas(code).then(fn);
52665321
}
52675322

5268-
shader_to_image({ shader, cell }, fn) {
5323+
pause() {
5324+
this.setAttribute('cssd-paused-animation', true);
5325+
for (let animation of this.animations) {
5326+
animation.pause();
5327+
}
5328+
}
5329+
5330+
resume() {
5331+
this.removeAttribute('cssd-paused-animation');
5332+
for (let animation of this.animations) {
5333+
animation.resume();
5334+
}
5335+
}
5336+
5337+
shader_to_image({ shader, cell, id }, fn) {
52695338
let parsed = typeof shader === 'string' ? parse$7(shader) : shader;
52705339
let element = this.doodle.getElementById(cell);
5340+
5341+
const set_shader_prop = (v) => {
5342+
element.style.setProperty(id, `url(${v})`);
5343+
};
5344+
52715345
const tick = (value) => {
5272-
if(typeof value === 'function') {
5273-
let currentImage;
5274-
const update = (t) => {
5275-
if(currentImage === element.style.backgroundImage) {
5276-
element.style.backgroundImage = `url(${value(t)})`;
5277-
currentImage = element.style.backgroundImage;
5278-
requestAnimationFrame(update);
5279-
}
5280-
};
5281-
requestAnimationFrame(update);
5282-
const ret = value(0);
5283-
element.style.backgroundImage = `url(${ret})`;
5284-
currentImage = element.style.backgroundImage;
5346+
if (typeof value === 'function') {
5347+
let animation = createAnimationFrame(t => {
5348+
set_shader_prop(value(t));
5349+
});
5350+
this.animations.push(animation);
52855351
return '';
52865352
}
5287-
return value;
5353+
set_shader_prop(value);
52885354
};
5355+
52895356
let { width, height } = element && element.getBoundingClientRect() || {
52905357
width: 0, height: 0
52915358
};
5292-
let ratio = window.devicePixelRatio || 1;
52935359

5360+
let ratio = window.devicePixelRatio || 1;
52945361
if (!parsed.textures.length || parsed.ticker) {
52955362
draw_shader(parsed, width, height).then(tick).then(fn);
52965363
}
@@ -5382,20 +5449,14 @@ void main() {
53825449
);
53835450

53845451
return Promise.all(mappings).then(mapping => {
5385-
if (input.replaceAll) {
5386-
mapping.forEach(({ id, value }) => {
5387-
input = input.replaceAll(
5388-
'${' + id + '}',
5389-
/^canvas/.test(id) ? value : `url(${value})`
5390-
);
5391-
});
5392-
} else {
5393-
mapping.forEach(({ id, value }) => {
5394-
input = input.replace(
5395-
'${' + id + '}',
5396-
/^canvas/.test(id) ? value : `url(${value})`
5397-
);
5398-
});
5452+
for (let {id, value} of mapping) {
5453+
/* default to data-uri for doodle and pattern */
5454+
let target = `url(${value})`;
5455+
/* canvas uses css painting api */
5456+
if (/^canvas/.test(id)) target = value;
5457+
/* shader uses css vars */
5458+
if (/^shader/.test(id)) target = `var(--${id})`;
5459+
input = input.replaceAll('${' + id + '}', target);
53995460
}
54005461
return input;
54015462
});
@@ -5605,11 +5666,9 @@ void main() {
56055666
.map(n => `${ n }: inherit;`)
56065667
.join('');
56075668
return `
5608-
* {
5609-
box-sizing: border-box
5610-
}
5611-
*::after, *::before {
5612-
box-sizing: inherit
5669+
*, *::after, *::before {
5670+
box-sizing: border-box;
5671+
animation-play-state: var(--cssd-animation-play-state) !important;
56135672
}
56145673
:host, .host {
56155674
display: block;
@@ -5639,6 +5698,10 @@ void main() {
56395698
width: 100%;
56405699
height: 100%;
56415700
}
5701+
:host([cssd-paused-animation]) {
5702+
--cssd-animation-play-state: paused;
5703+
animation-play-state: paused !important;
5704+
}
56425705
`;
56435706
}
56445707

0 commit comments

Comments
 (0)