Wykonuję Kalejdoskop na mojej stronie. Wszystko, co robi, to zrobić zdjęcie (za pomocą Drag & Drop lub domyślny obraz przy załadunku) i skopiować go 10 razy (po jednym dla każdego plasterka kalejdoskopu). Przy ruchu myszką, obrót i skala plasterków są regulowane w celu uzyskania pożądanego efektu.Rysunek na płótnie zajmuje dużo czasu w Safari, ale nie w Chrome ani w FF
W Google Chrome i Firefox działa bezproblemowo, bez opóźnień. Jednak w Safari strona internetowa nie nadaje się do użytku, ponieważ jest zbyt wolna. Czy czegoś brakuje?
Oto JSFiddle pokazujący problem. Uwaga! Próbowałem już zastąpić setTimeout (aktualizacja, 1000/60) przez RequestAnimationFrame, bez żadnych ulepszeń.
JSFiddle: Link
$(document).ready(function() {
//SCRIPT KALEIDOSCOPE BASE
var DragDrop, Kaleidoscope, c, dragger, gui, i, image, kaleidoscope, len, onChange, onMouseMoved, options, ref, tr, tx, ty, update,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
Kaleidoscope = (function() {
Kaleidoscope.prototype.HALF_PI = Math.PI/2;
Kaleidoscope.prototype.TWO_PI = Math.PI * 2;
var optimal_radius = window.innerHeight;
if (window.innerWidth > optimal_radius) {
optimal_radius = window.innerWidth;
}
function Kaleidoscope(options1) {
var key, ref, ref1, val;
this.options = options1 != null ? options1 : {};
this.defaults = {
offsetRotation: 0.0,
offsetScale: 1.0,
offsetX: 0.0,
offsetY: 0.0,
radius: optimal_radius/1.4,
slices: 12,
zoom: 1.0
};
ref = this.defaults;
for (key in ref) {
val = ref[key];
this[key] = val;
}
ref1 = this.options;
for (key in ref1) {
val = ref1[key];
this[key] = val;
}
if (this.domElement == null) {
this.domElement = document.getElementById('kaleidoscope');
}
if (this.context == null) {
this.context = this.domElement.getContext('2d');
}
if (this.image == null) {
this.image = document.createElement('img');
}
}
Kaleidoscope.prototype.draw = function() {
var cx, i, index, ref, results, scale, step;
this.domElement.width = this.domElement.height = this.radius * 2;
this.context.fillStyle = this.context.createPattern(this.image, 'repeat');
scale = this.zoom * (this.radius/Math.min(this.image.width, this.image.height));
step = this.TWO_PI/this.slices;
cx = this.image.width/2;
results = [];
for (index = i = 0, ref = this.slices; 0 <= ref ? i <= ref : i >= ref; index = 0 <= ref ? ++i : --i) {
this.context.save();
this.context.translate(this.radius, this.radius);
this.context.rotate(index * step);
this.context.beginPath();
this.context.moveTo(-0.5, -0.5);
this.context.arc(0, 0, this.radius, step * -0.51, step * 0.51);
this.context.lineTo(0.5, 0.5);
this.context.closePath();
this.context.rotate(this.HALF_PI);
this.context.scale(scale, scale);
this.context.scale([-1, 1][index % 2], 1);
this.context.translate(this.offsetX - cx, this.offsetY);
this.context.rotate(this.offsetRotation);
this.context.scale(this.offsetScale, this.offsetScale);
this.context.fill();
results.push(this.context.restore());
}
return results;
};
return Kaleidoscope;
})();
DragDrop = (function() {
function DragDrop(callback, context, filter) {
var disable;
this.callback = callback;
this.context = context != null ? context : document;
this.filter = filter != null ? filter : /^image/i;
this.onDrop = bind(this.onDrop, this);
disable = function(event) {
event.stopPropagation();
return event.preventDefault();
};
this.context.addEventListener('dragleave', disable);
this.context.addEventListener('dragenter', disable);
this.context.addEventListener('dragover', disable);
this.context.addEventListener('drop', this.onDrop, false);
}
DragDrop.prototype.onDrop = function(event) {
var file, reader;
event.stopPropagation();
event.preventDefault();
file = event.dataTransfer.files[0];
if (this.filter.test(file.type)) {
reader = new FileReader;
reader.onload = (function(_this) {
return function(event) {
return typeof _this.callback === "function" ? _this.callback(event.target.result) : void 0;
};
})(this);
return reader.readAsDataURL(file);
}
};
return DragDrop;
})();
image = new Image;
image.onload = (function(_this) {
return function() {
return kaleidoscope.draw();
};
})(this);
image.src = 'img/kaleidoscope.jpg';
kaleidoscope = new Kaleidoscope({
image: image,
slices: 10
});
kaleidoscope.domElement.style.position = 'absolute';
kaleidoscope.domElement.style.marginLeft = -kaleidoscope.radius + 'px';
kaleidoscope.domElement.style.marginTop = -kaleidoscope.radius + 'px';
kaleidoscope.domElement.style.left = '50%';
kaleidoscope.domElement.style.top = '50%';
document.getElementsByTagName('header')[0].appendChild(kaleidoscope.domElement);
dragger = new DragDrop(function(data) {
return kaleidoscope.image.src = data;
});
tx = kaleidoscope.offsetX;
ty = kaleidoscope.offsetY;
tr = kaleidoscope.offsetRotation;
onMouseMoved = (function(_this) {
return function(event) {
var cx, cy, dx, dy, hx, hy;
cx = window.innerWidth/10;
cy = window.innerHeight/10;
dx = event.pageX/window.innerWidth;
dy = event.pageY/window.innerHeight;
hx = dx - 0.5;
hy = dy - 0.5;
tx = hx * kaleidoscope.radius * -2;
ty = hy * kaleidoscope.radius * 2;
return tr = Math.atan2(hy, hx);
};
})(this);
window.addEventListener('mousemove', onMouseMoved, false);
options = {
interactive: true,
ease: 0.1
};
(update = (function(_this) {
return function() {
var delta, theta;
if (options.interactive) {
delta = tr - kaleidoscope.offsetRotation;
theta = Math.atan2(Math.sin(delta), Math.cos(delta));
kaleidoscope.offsetX += (tx - kaleidoscope.offsetX) * options.ease;
kaleidoscope.offsetY += (ty - kaleidoscope.offsetY) * options.ease;
kaleidoscope.offsetRotation += (theta - kaleidoscope.offsetRotation) * options.ease;
kaleidoscope.draw();
}
return setTimeout(update, 1000/60);
};
})(this))();
onChange = (function(_this) {
return function() {
kaleidoscope.domElement.style.marginLeft = -kaleidoscope.radius + 'px';
kaleidoscope.domElement.style.marginTop = -kaleidoscope.radius + 'px';
options.interactive = false;
return kaleidoscope.draw();
};
})(this);
});
Z tego co widziałem, problem występuje tylko wtedy, gdy płótno jest na pełnym ekranie. Jeśli pojawi się na małej powierzchni, działa płynnie. Jednak na mojej stronie będzie to pełny ekran.
Upewnij się, że w Safari jest włączone przyspieszone renderowanie sprzętu (GPU). – Blindman67
@ Blindman67 Próbowałem włączyć go za pomocą menu debugowania, ale nadal nie poprawia szybkości odtwarzania. – Lucio
Masz w tym coś naprawdę złego: ** nie zmieniaj rozmiaru elementu canvas w każdej klatce **, powoduje to ponowne odbicie strony i resetuje wszystkie właściwości twojego płótna; nie twórz wzorca w każdej klatce, jeśli zawsze jest taka sama, jaka będzie używana; unikaj przy maksymalnych 'save' i' restore', kiedy potrzebujesz zresetować transformacje (wolisz 'setTransform (1,0,0,1,0,0);'); nie używaj 'setTimeout' do tworzenia pętli animacji, preferuj' requestAnimationFrame'. Ale nawet przy [wszystko to naprawione] (https://jsfiddle.net/sd1skrj8/4/show/), Safari po prostu nie może sobie z tym poradzić ... Przepraszam. Próbowałem; nie udało się. – Kaiido