Skip to content

Instantly share code, notes, and snippets.

@jake-sl
Created April 15, 2023 04:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jake-sl/e66c58cc6b94348168caf285dc6dcfe0 to your computer and use it in GitHub Desktop.
Save jake-sl/e66c58cc6b94348168caf285dc6dcfe0 to your computer and use it in GitHub Desktop.
vYVGyyo
<body>
<input type="file" id="image-input" accept="image/*">
<input type="file" id="shadow-input" accept="image/*">
<label for="color1">Color 1:</label>
<input type="color" id="color1" value="#000000">
<label for="color2">Color 2:</label>
<input type="color" id="color2" value="#ffffff">
<label for="bg-color">Background Color:</label>
<input type="color" id="bg-color" value="#ffffff">
<canvas id="image-canvas"></canvas>
<button id="clear-shadow-btn">Clear Shadow</button>
<script src="main.js"></script>
</body>
const imageInput = document.getElementById('image-input');
const shadowInput = document.getElementById('shadow-input');
const color1 = document.getElementById('color1');
const color2 = document.getElementById('color2');
const bgColor = document.getElementById('bg-color');
const canvas = document.getElementById('image-canvas');
const ctx = canvas.getContext('2d');
let img = new Image();
let shadowImg = new Image();
const clearShadowBtn = document.getElementById('clear-shadow-btn');
imageInput.addEventListener('change', e => {
const reader = new FileReader();
reader.onload = event => {
img.src = event.target.result;
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
updateImage();
};
};
reader.readAsDataURL(e.target.files[0]);
});
shadowInput.addEventListener('change', e => {
const reader = new FileReader();
reader.onload = event => {
shadowImg.src = event.target.result;
shadowImg.onload = () => {
updateImage();
};
};
reader.readAsDataURL(e.target.files[0]);
});
clearShadowBtn.addEventListener('click', () => {
shadowImg.src = '';
updateImage();
});
function updateImage() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw the image in grayscale
ctx.filter = 'grayscale(100%)';
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.filter = 'none';
// Draw the color gradient onto a temporary canvas
const tempCanvas = document.createElement('canvas');
tempCanvas.width = canvas.width;
tempCanvas.height = canvas.height;
const tempCtx = tempCanvas.getContext('2d');
const gradient = tempCtx.createLinearGradient(0, 0, canvas.width, canvas.height);
gradient.addColorStop(0, color1.value);
gradient.addColorStop(1, color2.value);
tempCtx.fillStyle = gradient;
tempCtx.fillRect(0, 0, canvas.width, canvas.height);
// Use the source-atop composite operation to only draw the gradient where the grayscale image is opaque
ctx.globalCompositeOperation = 'source-atop';
ctx.drawImage(tempCanvas, 0, 0, canvas.width, canvas.height);
// Reset the composite operation
ctx.globalCompositeOperation = 'source-over';
// Draw the shadow image on top with blend mode set to screen
if (shadowImg.src !== '') {
ctx.globalCompositeOperation = 'multiply';
ctx.drawImage(shadowImg, 0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'source-over';
}
}
function updateBackground() {
canvas.style.backgroundColor = bgColor.value;
}
color1.addEventListener('input', updateImage);
color2.addEventListener('input', updateImage);
bgColor.addEventListener('input', updateBackground);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment