I'm updating DOM element's brightness/contrast from JavaScript:
let style = `brightness(${brightness}%) contrast(${contrast}%)`;
element.style.filter = style;
This happens when the user holds left mouse button and moves cursor. However, the brightness/contrast does NOT change in Safari (on Mac) unless the scroll bars are visible. However, the brightness does change in other browsers (Chrome, Firefox, Edge). Is it a bug in Safari? How do I make it work in Safari?
Demo: https://l36vng.csb.app/
Code: https://codesandbox.io/s/charming-vaughan-l36vng?file=/main.js:2207-2306
PS. This also does not work in Safari on iOS (if I include touch event handlers to the code above). My Mac Safari version is 16.1.
CodePudding user response:
This seems to be fixed in the latest Technology Preview (Release 160 (Safari 16.4, WebKit 18615.1.14.3)).
For the time being, you can workaround the issue by adding a super fast transition on the filter property, this will make current stable happy and update the filter as expected.
// Change brightness/contrast of the image by holding
// left mouse button on the image and moving cursor.
// Moving horizontally changes brightness,
// moving vertically changes contrast.
class Brightness {
constructor(element) {
this.element = element;
// x and y mouse coordinates of the cursor
// when the brightness change was started
this.startPosition = null;
this.brightnessPercent = 100;
// Current brightness/contrast percentage.
this.currentAmount = {
brightness: 100,
contrast: 100
};
// True if the user holds left mouse bottom, which
// indicates that brightness is being changed.
// False by default or when the left mouse button is released.
this.active = false;
this.addEventListeners();
}
addEventListeners() {
let element = this.element;
// Start changing brightness
// -----------------
element.addEventListener("mousedown", (e) => {
if (e.button !== 0) return; // Not a left mouse button
this.active = true;
e.preventDefault();
this.startChange(e);
});
// End changing brightness
// -----------------
document.addEventListener("mouseup", () => {
this.active = false;
});
// Drag the pointer over the bar
// -----------------
document.addEventListener("mousemove", (e) => {
if (!this.active) return;
this.change(e);
});
}
startChange(e) {
this.startPosition = this.positionFromCursor(e);
}
change(e) {
let position = this.positionFromCursor(e);
let xChange = position.x - this.startPosition.x;
this.changeCurrentAmount(xChange, "brightness");
let yChange = position.y - this.startPosition.y;
this.changeCurrentAmount(yChange, "contrast");
this.changeImageStyle();
}
changeCurrentAmount(change, type) {
change /= 2; // Decrease rate of change
change = Math.round(change);
let amount = 100 change;
if (type === "contrast") amount = 100 - change;
if (amount < 0) amount = 0;
this.currentAmount[type] = amount;
}
changeImageStyle() {
let brightness = this.currentAmount.brightness;
let contrast = this.currentAmount.contrast;
let css = `brightness(${brightness}%) contrast(${contrast}%)`;
this.element.style.filter = css;
}
positionFromCursor(e) {
let pointerX = e.pageX;
let pointerY = e.pageY;
if (e.touches && e.touches.length > 0) {
pointerX = e.touches[0].pageX;
pointerY = e.touches[0].pageY;
}
return { x: pointerX, y: pointerY };
}
}
document.addEventListener("DOMContentLoaded", function () {
const imageElement = document.querySelector(".Image");
new Brightness(imageElement);
});
.Image {
/* Safari bug workaround */
transition: filter 1e-6s linear;
}
<img
width="512"
height="512"
src="https://64.media.tumblr.com/df185589006321d70d37d1a59040d7c3/df57f19b4b4b783a-cb/s250x400/e76347d6b1cb4aa08839036fb0407a9f6108a0ab.jpg"
/>