Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: third_party/WebKit/ManualTests/compositor-worker/sticky/js/sticky.js

Issue 1547893003: WIP - compositor worker mega patch. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 (function(scope) {
2 "use strict";
3 function getStickyElements(nodelist, node) {
4 nodelist = nodelist || [];
5 node = node || document.body;
6 if (node.classList.contains('sticky'))
7 nodelist.push(node);
8 // Q: How do we support this position property?
9 // if (getComputedStyle(node).position == 'sticky')
10 // nodelist.append(node);
11
12 // Q: How do we just do work on sticky elements rather than entire DOM?
13 for (var i = 0; i < node.children.length; ++i) {
14 getStickyElements(nodelist, node.children[i]);
15 }
16 return nodelist;
17 }
18
19 function installStickyHandler(scroller, element, sticky_info) {
20 var main_info = {
21 'sticky': new WrapElement(element),
22 'scroller': new WrapElement(scroller),
23 'limits': sticky_info.limits,
24 };
25
26 // Install a viewport observer to update position on the main thread.
27 var observer = new ViewportObserver(updateStickyPosition.bind(null, main_inf o));
28 observer.observe(scroller);
29 // TODO: Install compositor worker to update on compositor thread.
30 }
31
32 function updateStickyPosition(info) {
33 // Find sticky position
34 // Note: top and left take priority over bottom and right as per spec:
35 var offsetX, offsetY;
36 if (info.limits.y.attachment == 'top')
37 offsetY = Math.min(Math.max(info.limits.y.min, info.scroller.scrollTop() - info.limits.y.top), info.limits.y.max);
38 if (info.limits.y.attachment == 'bottom')
39 offsetY = Math.max(Math.min(info.limits.y.max, info.scroller.scrollTop() + info.limits.y.bottom), info.limits.y.min);
40 if (info.limits.x.attachment == 'left')
41 offsetX = Math.min(Math.max(info.limits.x.min, info.scroller.scrollLeft() - info.limits.x.left), info.limits.x.max);
42 if (info.limits.x.attachment == 'right')
43 offsetX = Math.max(Math.min(info.limits.x.max, info.scroller.scrollLeft() + info.limits.x.right), info.limits.x.min);
44
45 // Q: How should we really move the element around? This is overloading the top / left properties which has a specific meaning for sticky.
46 // A: Probably hidden position attributes (e.g. used left, used top), but ho w do we want to expose these?
47 info.sticky.setTransform(offsetX || 0, offsetY || 0, info.limits.id);
48 }
49
50 function gatherStickyInfo() {
51 var nodes = getStickyElements();
52 scope.sticky_info = [];
53 for (var i = 0; i < nodes.length; i++) {
54 var node = nodes[i];
55 var cb = getContainingBlockElement(node);
56 var s = getContainingScrollingElement(node);
57
58 // Q: Need to be notified when sticky node is removed / moved - Mutation O bserver?
59 var info = {
60 sticky: scope.CompositorProxy ? new CompositorProxy(node, ['transform']) : undefined,
61 scroller: scope.CompositorProxy ? new CompositorProxy(s, ['scrollTop', ' scrollLeft']) : undefined,
62 limits: scope.getStickyOffsetLimits(node, cb, s, getStickyOffsets(node)) ,
63 }
64 scope.sticky_info.push(info);
65 installStickyHandler(s, node, info);
66 }
67 if (scope.CompositorWorker) {
68 scope.worker = new CompositorWorker('js/sticky.js');
69 scope.worker.postMessage(scope.sticky_info);
70 }
71 }
72
73 scope.getStickyOffsetLimits = function(sticky, containing, scroller, clamp) {
74 var c = containing.getBoundingClientRect();
75 var s = sticky.getBoundingClientRect();
76 var v = getViewportRect(scroller);
77
78 var limits = {
79 id: sticky.id,
80 x: {
81 left: s.left + scroller.scrollLeft - (clamp.left || 0),
82 right: v.right - s.right - scroller.scrollLeft - (clamp.right || 0),
83 min: c.left - s.left + (clamp.left || 0),
84 max: c.right - s.right - (clamp.right || 0),
85 },
86 y: {
87 top: s.top + scroller.scrollTop - (clamp.top || 0),
88 bottom: v.bottom - s.bottom - scroller.scrollTop - (clamp.bottom || 0),
89 min: c.top - s.top + (clamp.top || 0),
90 max: c.bottom - s.bottom - (clamp.bottom || 0),
91 }};
92 if (clamp.bottom)
93 limits.y.attachment = 'bottom';
94 if (clamp.top)
95 limits.y.attachment = 'top';
96 if (clamp.right)
97 limits.x.attachment = 'right';
98 if (clamp.left)
99 limits.x.attachment = 'left';
100 return limits;
101 }
102
103 function getStickyOffsets(node) {
104 var style = getComputedStyle(node);
105 // Note: this assumes top/left/right/bottom will be set in 'px'.
106 // TODO: Support percentage?
107 var info = {
108 'top': style.top == 'auto' ? undefined : parseFloat(style.top),
109 'left': style.left == 'auto' ? undefined : parseFloat(style.left),
110 'right': style.right == 'auto' ? undefined : parseFloat(style.right),
111 'bottom': style.bottom == 'auto' ? undefined : parseFloat(style.bottom),
112 };
113 node.style.top = node.style.left = node.style.right = node.style.bottom = 'a uto';
114 return info;
115 }
116
117 scope.compositorUpdate = function() {
118 for (var i = 0; i < scope.sticky_info.length; i++) {
119 updateStickyPosition(scope.sticky_info[i]);
120 }
121 scope.requestAnimationFrame(scope.compositorUpdate);
122 }
123
124 scope.WrapElement = function(element) {
125 this.element_ = element;
126 }
127 scope.WrapElement.prototype.scrollTop = function() { return this.element_.scro llTop; };
128 scope.WrapElement.prototype.scrollLeft = function() { return this.element_.scr ollLeft; };
129 scope.WrapElement.prototype.setTransform = function(x, y, id, extra) {
130 this.element_.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
131 };
132
133 scope.WrapCompositorProxy = function(proxy) {
134 this.proxy_ = proxy;
135 }
136 scope.WrapCompositorProxy.prototype.scrollTop = function() { return this.proxy _.scrollTop; };
137 scope.WrapCompositorProxy.prototype.scrollLeft = function() { return this.prox y_.scrollLeft; };
138 scope.WrapCompositorProxy.prototype.setTransform = function(x, y, id, extra) {
139 var t = this.proxy_.transform;
140 t.m41 = x;
141 t.m42 = y;
142 this.proxy_.transform = t;
143 };
144
145
146 function initCompositorWorker() {
147 console.log('Init on compoositor worker');
148 self.onmessage = function(e) {
149 scope.sticky_info = e.data;
150 // Wrap all of the compositor proxies to match expectations.
151 for (var i = 0; i < sticky_info.length; i++) {
152 sticky_info[i].sticky = new scope.WrapCompositorProxy(sticky_info[i].sti cky);
153 sticky_info[i].scroller = new scope.WrapCompositorProxy(sticky_info[i].s croller);
154 }
155 scope.requestAnimationFrame(scope.compositorUpdate);
156 console.log('onmessage on compositor');
157 };
158 }
159
160
161 if (scope.window) {
162 scope.document.addEventListener('DOMContentLoaded', gatherStickyInfo);
163 } else {
164 scope.sticky_info = [];
165 initCompositorWorker();
166 }
167 })(self);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698