I have two canvas and when I draw something on the first one, I want to be able to draw the exact same thing but flipped like a mirror in the second one.
So I tried using CSS Transform, but it makes the mouse movement on the second Canvas not accurate.
This is my code:
http://jsfiddle.net/q5vZc/
#paint {
width: 100%;
height: 50%;
float: left;
}
#paint2 {
float: right;
width: 100%;
height: 50%;
/*pointer-events: none;*/
-moz-transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
-o-transform: scale(-1, 1);
transform: scale(-1, 1);
}
Is there a way to fix this?
I created a function that flips the mouse movement on the second canvas. In which I pass the mouse point where it was clicked and the width of the canvas.
function flipHorizontal(ponto, width) {
var x_linha = (width- ponto.x);
var y_linha = (ponto.y);
var flipped = {
x: x_linha,
y: y_linha
};
return flipped;
}
Do not use css scaling unless you master it, strange result will follow.
Most simple in your case is to remove any css, and just copy the left half by hand into the right part.
So use only one canvas, draw only on the left part, and each time you finished your drawings, call this function to have the left part mirrored :
// copy the the left part of the canvas on its right part
function mirrorContext(context) {
var canvas = context.canvas;
var width = canvas.width;
var height = canvas.height;
// preserve context
context.save();
// translate to middle of right part of canvas
context.translate(3*width/4, height/2);
// flip x direction
context.scale(-1, 1);
// draw left part on right part, reversed
context.drawImage(canvas
/* take left part of canvas... */ ,0, 0, width/2, height
/* ... copy it on right part */ ,-width/4, -height/2, width/2, height
);
// cancel any context change
context.restore();
}
http://jsbin.com/gigazeka/1/edit?js,output
Related
I am rotating a hexagonal (6 sides shape) icon 60 degrees upon hovering and want it to stay rotated as long as you don't hover it again. If you hover the icon again, it will rotate another 60 degrees.
Is this effect possible with pure CSS ? The important part is for the icon to stay rotated for as long as you don't hover it again and to rotate another 60 degrees if you hover it.
I've tried the usual method with a transition and a transform, but the icon comes back at its original rotation when you unhover it.
.icon:hover {
transition: transform 0.5s;
transform: rotate(60deg);
}
With JS you rotate the square by 10 degrees each time you hover over it:
let div = document.querySelector(".a");
let i = 10; //degrees to rotate
const rotateIt = () => {
div.style.transform="rotate(" + i + "deg)";
i = i + 10;
}
div.addEventListener("mouseover", rotateIt);
div.a {
width: 100px;
height: 100px;
background-color: red;
}
div.a:hover {
transform: rotate(20deg);
}
<div class="a"></div>
This is pretty hard to explain so I made a codepen. Try opening it in Chrome and in Safari and click in the codepen viewport to see the difference:
https://codepen.io/matt_o_tron_5000/pen/gOMaKmY
Basically, we have this dot that follows the cursor around with the help of some javascript. A CSS animation makes it gently grow/shrink at all times, and when you click the dot reacts by shrinking substantially.
In Chrome and Firefox, when you click, the dot shrinks to the center, where the mouse pointer is located. But in Safari, it shrinks to the upper left corner. I found that by removing the CSS animation, this is resolved. But I can't figure out why.
Any idea how I can fix this behavior in Safari?
Aaaaaand apparently I can't post this unless my codepen link is "accompanied by code". So here's some code.
// HTML
<span id="custom-cursor"></span>
// CSS
#custom-cursor {
position: fixed;
display: block;
width: 6rem;
height: 6rem;
border-radius: 50%;
background-color: red;
transform: translate3d(-50%, -50%, 0) scale(1);
transition: 0.1s ease-out;
transition-property: width, height, transform;
animation: growshrink 4s infinite;
&.clicking {
width: 1rem;
height: 1rem;
}
}
#keyframes growshrink {
0% {
transform: translate3d(-50%, -50%, 0) scale(1);
}
50% {
transform: translate3d(-50%, -50%, 0) scale(1.3);
}
100% {
transform: translate3d(-50%, -50%, 0) scale(1);
}
}
// Javascript
(function () {
var follower, mouseX, mouseY, positionElement, timer;
follower = document.getElementById('custom-cursor');
console.log(follower);
mouseX = event => { return event.clientX; };
mouseY = event => {return event.clientY;};
positionElement = event => {
var mouse;
mouse = {
x: mouseX(event),
y: mouseY(event),
};
follower.style.top = mouse.y + 'px';
follower.style.left = mouse.x + 'px';
};
window.onmousemove = event => {
if(!timer){timer = false;}
var _event;
_event = event;
return timer = setTimeout(() => {
return positionElement(_event);
}, 5);
};
}).call(this);
$(document).on('mousedown', function() {
$('#custom-cursor, #imghover-cursor').addClass('clicking');
});
$(document).on('mouseup', function() {
$('#custom-cursor, #imghover-cursor').removeClass('clicking');
});
Browsers render code differently.... one can either update its code so that it behaves like one wants in the 'supported browsers' for the project OR go a user-agent sniffing way/per browser-type approach I don't recommend that and I never do that just because there's almost always a way to do it with option #1 which is much simpler, cleaner and easier [changing the library you use and/or tweaking your existing code].
When I suggest 'changing the library for animation' I mean more specifically use an open-source community-vetted one like GSAP. https://greensock.com/gsap/
But if you want to go down the rabbit hole, please start here :
https://github.com/WhichBrowser/Parser-PHP
I am making a battleship style game and trying to work on the movement of the ships on the table. My idea is that you can drag and drop ships onto the table and when you click on the ship it changes from vertical to a horizontal position or other way around. Every ship has some css with two main parts Width and Height. Is it possible to make so that the Ships css width and height are swapped around when I click on the ship?
With javascript, you can change the CSS width using:
var el = document.querySelector("#yourObjectID");
el.style.width = "100px";
To change the height:
el.style.height = "100px";
To swap the height and width you could use an extra variable as you would swap any other variables.
If you are using a click listener, you can use this instead of creating a variable el and selecting the element with a query selector.
document.querySelector("#ship1").addEventListener('click', function(){
var newHeight = this.style.width;
this.style.width = this.style.height;
this.style.height = newHeight;
}, false);
.ship {
background: gray;
cursor: pointer;
}
<div id="ship1" class="ship" style="width: 100px; height: 50px;"></div>
I am unfortunately not too sure what you are trying to achieve. are you trying to swap the ships from vertical to horizontal or are you trying to swap the width and height with eachother.
If you are trying to rotate the ship you can do it like this:
With css and js you can rotate the ships like this:
html
<div id="MyID" onclick="ChangeClass()"></div>
js
function ChangeClass() {
var MyVar= document.getElementById("MyID")
MyVar.className="MyClass"
}
css
.MyClass{
/* rotates the class. webkit = chrome,safari ms = edge, moz = firefox, o = opera*/
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-o-transform: rotate(90deg);
}
you can change the ID and classes to your desired names.
I am wondering if anyone knows how exactly text color (or background-color) is animated using CSS transitions. Lets say we have:
.box {
background-color: red;
transition: background-color 2s ease-out;
}
.box:hover {
background-color: green;
}
So during two seconds of hovering the box will change color from red to green going through some brownish color.
What I want to know is what values are exactly being manipulated and how. Is it rgba? HEX? If so, how are these values changing? Going from rgb(255, 0, 0) through rgb(123, 122, 0) to rgb(0, 255, 0) linearly or something?
My main aim (apart from simple curiosity) is to be able to control the progress of a color change, stating that at time A the color should be 30% of the change, while at time B it should have 70% of the new color.
Hard to google as I just keep getting tutorials for CSS animations...
edit
To clarify I want to be able to stop the animation at a certain point/color depending on the app state, not just cycle through. The only way to do this will be if I know how the browser implementations work.
The interpolation between two colors during a transtion or an animation is done the same way like creating a gradient between the same two colors. The easiest way to understand it is to draw the gradient.
Here is an example to illustrate:
.box {
background-color: red;
width:20px;
height:50px;
margin-top:-5px;
animation: change 2s infinite alternate linear;
}
.container {
height:50px;
width:400px;
background:linear-gradient(to right,red,green);
}
#keyframes change {
to {
background-color:green;
transform:translateX(380px);
}
}
<div class="container">
</div>
<div class="box">
</div>
If you pick some colors you will see that the interpolation is quite easy and it's done in the RGB space. First we write our both color using rgb. In our case we have:
red = rgb(255,0,0)
green = rgb(0,128,0) /* and not rgb(0,255,0) */
Then we simply interpolate each color alone (R, G and B) to obtain something like:
rgb(255,0,0)
rgb(254,2,0)
rgb(253,4,0)
rgb(252,6,0)
....
rgb(1,126,0)
rgb(0,128,0)
The below is a simple approximation but to be more accurate you need to either consider the duration or the size of the gradient. If we consider our gradient, we have defined 400px of width so we will have 400 different colors for each pixel. For the red we are moving from 255 to 0 so we have 256 values that we divide by 400 thus our step will be 0.64. For the green we will have a step of 0.3225.
The color of each pixel will be rgb(255 - n*0.64,0 + n*0.3225,0) where n is the pixel number from 1 to 400.
We do the same logic for the transition but we consider the time instead of width. We have 2s and if we suppose that the browser draw each 0.01s, we will need 200 values and so on ..
In addition, you should consider the rounding of the values which may not be the same for each browser. You should also know the granularity when it comes to times. I considered 0.01s as an example to illustrate but I don't know the real value. Most important, you should know the rgb value for each color defined by a keyword. A green may not be the same across browsers.
To illustrate the above calculation here is an example where I will draw the gradient based on both color and it will reflect the transition/animation
var sR = (250 - 10) / 400;
var sG = (30 - 80) / 400;
var sB = (150 - 255) / 400;
var canvas = document.querySelector('.container');
var ctx = canvas.getContext('2d');
for (var i = 0; i <= 400; i++) {
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(i, 0);
ctx.lineTo(i, 50);
ctx.strokeStyle = "rgb(" + (250 - i * sR) + "," + (30 - i * sG) + "," + (150 - i * sB) + ")";
ctx.stroke();
}
.box {
background-color: rgb(250, 30, 150);
width: 20px;
height: 50px;
margin-top: -10px;
animation: change 2s infinite alternate linear;
}
#keyframes change {
to {
background-color: rgb(10, 80, 255);
transform: translateX(380px);
}
}
<canvas class="container" width="400" height="50"></canvas>
<div class="box">
</div>
Edit:
Browser implementation varies depending on the browser. Since you clarified that your main aim is to be able to control the progress of a color change, I addressed that in this answer below with a solution.
Beyond that, you may want to take a look at this CSS property, transition-timing-function.
Futhermore, a quote from MDN on Using CSS transitions:
With CSS transitions enabled, changes occur at time intervals that follow an acceleration curve, all of which can be customized.
Animations that involve transitioning between two states are often called implicit transitions as the states in between the start and final states are implicitly defined by the browser.
Original answer:
It's true that CSS animations are one way to go here. Besides that you might use javascript for this kind of fine-tuned control.
So for example, you can set up an animation like this:
#keyframes specialFade {
0% {
background-color: rgb(255, 0, 0);
}
20% {
background-color: rgb(175, 80, 0)
}
50% {
background-color: rgb(80, 175, 0)
}
100% {
background-color: rgb(0, 255, 0)
}
}
I calculated these rgb values myself, based on what I'd call "about 30% and 70%" of the color change.
In a 5 second animation-duration, the 20%, 50%, etc would refer to the 1 second mark and 2.5 second mark respectively. No way to set up specific timing in CSS (hence my mention of JS above).
I have a colored png image with transparency. I would like to use css filter to make the whole image white but leave the transparency as it is.
Is that possible in CSS?
You can use
filter: brightness(0) invert(1);
html {
background: red;
}
p {
float: left;
max-width: 50%;
text-align: center;
}
img {
display: block;
max-width: 100%;
}
.filter {
-webkit-filter: brightness(0) invert(1);
filter: brightness(0) invert(1);
}
<p>
Original:
<img src="http://i.stack.imgur.com/jO8jP.gif" />
</p>
<p>
Filter:
<img src="http://i.stack.imgur.com/jO8jP.gif" class="filter" />
</p>
First, brightness(0) makes all image black, except transparent parts, which remain transparent.
Then, invert(1) makes the black parts white.
To my knowledge, there is sadly no CSS filter to colorise an element (perhaps with the use of some SVG filter magic, but I'm somewhat unfamiliar with that) and even if that wasn't the case, filters are basically only supported by webkit browsers.
With that said, you could still work around this and use a canvas to modify your image. Basically, you can draw an image element onto a canvas and then loop through the pixels, modifying the respective RGBA values to the colour you want.
However, canvases do come with some restrictions. Most importantly, you have to make sure that the image src comes from the same domain as the page. Otherwise the browser won't allow you to read or modify the pixel data of the canvas.
Here's a JSFiddle changing the colour of the JSFiddle logo.
//Base64 source, but any local source will work
var src = "data:image/png;base64,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";
var canvas = document.getElementById("theCanvas");
var ctx = canvas.getContext("2d");
var img = new Image;
//wait for the image to load
img.onload = function() {
//Draw the original image so that you can fetch the colour data
ctx.drawImage(img,0,0);
var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
/*
imgData.data is a one-dimensional array which contains
the respective RGBA values for every pixel
in the selected region of the context
(note i+=4 in the loop)
*/
for (var i = 0; i < imgData.data.length; i+=4) {
imgData.data[i] = 255; //Red, 0-255
imgData.data[i+1] = 255; //Green, 0-255
imgData.data[i+2] = 255; //Blue, 0-255
/*
imgData.data[i+3] contains the alpha value
which we are going to ignore and leave
alone with its original value
*/
}
ctx.clearRect(0, 0, canvas.width, canvas.height); //clear the original image
ctx.putImageData(imgData, 0, 0); //paint the new colorised image
}
//Load the image!
img.src = src;
body {
background: green;
}
<canvas id="theCanvas"></canvas>