If you decrease the grasycale
, what will happen is that the image will not be "opaque" and you will see the color if you break the hue and if you use contrast
and saturation
. It would be very simple if there was a "fill" option. One way to get the desired effect is through Canvas. All you have to do is draw the image, get its imageData
and overwrite the painted colors.
Example
let palette = {
orange: {
red: '243',
green: '156',
blue: '18'
},
midnight: {
red: '44',
green: '62',
blue: '80'
},
greensea: {
red: '22',
green: '160',
blue: '130'
}
}
let orange = document.getElementById('orange');
let midnight = document.getElementById('midnight');
let greensea = document.getElementById('greensea');
drawImage(orange, palette.orange);
drawImage(midnight, palette.midnight);
drawImage(greensea, palette.greensea);
function drawImage(canvas, color) {
let ctx = canvas.getContext('2d');
let img = new Image();
img.onload = draw;
fetchImage("https://i.imgur.com/XXJf1A7.png")
.then(b64 => img.src = b64);
function draw() {
let hRatio = canvas.width / img.width;
let vRatio = canvas.height / img.height;
let ratio = Math.min(hRatio, vRatio);
let centerX = (canvas.width - img.width * ratio) / 2;
let centerY = (canvas.height - img.height * ratio) / 2
ctx.drawImage(
img,
0,
0,
img.width,
img.height,
centerX,
centerY,
img.width * ratio,
img.height * ratio
);
let imageData = ctx.getImageData(0, 0, img.width, img.height);
let data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
// rojo
data[i] = color.red;
// verde
data[i + 1] = color.green;
// azul
data[i + 2] = color.blue;
}
// sobreescribe la imagen original
ctx.putImageData(imageData, 0, 0);
}
}
function fetchImage(image) {
return new Promise((resolve) => {
let http = new XMLHttpRequest();
http.open('GET', image);
http.responseType = 'arraybuffer';
http.onload = function() {
if (this.status === 200 && this.readyState === 4) {
let blob = new Blob(
[this.response], {
type: 'image/png'
}
);
let url = window.URL.createObjectURL(blob);
let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
resolve(reader.result);
}
}
}
http.send();
});
}
*,
*:before,
*:after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
align-items: center;
display: flex;
flex-flow: column nowrap;
justify-content: center;
padding: 20px;
}
<!-- Para navegadores que no implementen Promise -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.0.5/es6-promise.auto.min.js"></script>
<canvas id="orange" width="500" height="300"></canvas>
<canvas id="midnight" width="500" height="300"></canvas>
<canvas id="greensea" width="500" height="300"></canvas>
Obviously you can draw the three shapes in a single Canvas stage to be able to move them. If you want to move them, you must associate a handler for the drag event in Canvas, obtain the shape according to the coordinates of the pointer and repaint the shape by updating the position according to the pointer.
Note: The images submitted to this procedure must be hosted locally or via base64, otherwise you will get the error "The canvas has been tainted by cross-origin data .
at drawImage ", which means that it can not deal with an image from another domain.