css mix-blend-mode and masks - css

Can an image be used as a mask when using the mix-blend-mode and webkit-mask-composites. For example can I use a white circle as a mask over another image to show only the area contained within both elements. Not what is outside either of the elements. See image the original image being the blue square and the mask being the circle. I want to only show the little bit of the image left after the mask is applied. Please note that this is a simple example my actual mask is a lot more complex and cannot be mimicked by a basic shape.mask

If you want jQuery I got a solution for you:
function addOverlapBox() {
var wrapper = $('#wrapper'),
div1 = $('#div1'),
div2 = $('#div2'),
overlay = $('<div id="overlay"></div>');
wrapper.append(overlay);
setInterval(function() {
theta += 0.01;
div1 = $('#div1'),
div2 = $('#div2'),
overlay = $('#overlay');
var l1=100 + 20*Math.cos(theta);
var t1=80 + 50*Math.sin(theta);
var w1=div1.width();
var h1=div1.height();
var l2=70 + 30*Math.cos(2*theta);//div2.offset().left-8;
var t2=90 + 32*Math.sin(theta);//div2.offset().top-8;
var w2=div2.width();
var h2=div2.height();
div1.css({'top': t1, 'left': l1});
div2.css({'top': t2, 'left': l2});
var top = Math.max(t1,t2);
var left = (l2>l1 && l2<(l1+w1)) ? l2 : (l1>l2 && l1<(l2+w2)) ? l1 : 0;
var width = Math.max(Math.min(l1+w1,l2+w2) - Math.max(l1,l2),0);
var height = Math.max(Math.min(t1+h1,t2+h2) - Math.max(t1,t2),0);
overlay.css({'top': top, 'left': left, 'width': width, 'height': height});
}, 10);
}
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
theta = 0;
addOverlapBox();
#wrapper {position:absolute; margin-top:0px; width:500px; height:300px;padding: 0px;}
#div1 {background-color:rgba(100, 20, 180, 1); width:80px; height:80px;position:absolute; left:60px; top: 50px; z-index:2;border:0;}
#div2 {background-color:rgba(249, 177, 67, 1); width:110px; height:70px; position:absolute; left:60px; top: 100px; z-index:1;border:0;}
#overlay {background-color:rgba(0, 0, 0, 1); position:absolute;z-index:10;border:0;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<div id="div1"></div>
<div id="div2"></div>
</div>
It's a animated so you can see that it's not just another div, where the divs intersect. That doesnt work with border-radius:50% i.e. tho because divs with rounded borders are actually still rectangles, just with a hidden border-radius.You can find a non-animated version here: http://jsfiddle.net/GApu5/32/

Probably you should use css property
clip-path
https://css-tricks.com/almanac/properties/c/clip/
if you want to just mask it.

Related

adding animation to flex-wrap

when it comes to wrap point how can we add animation?
maybe this can help:
we have a header and inside of that header we have container with flex attr and the direction is column when we resize our browser from bottom to top or when we changing height of browser those items suddenly reshape , I just want to add animation to this event.thx
<header>
<div class="container">
<div class="item1 item"></div>
<div class="item2 item"></div>
<div class="item3 item"></div></div></header>
header {
width: 200vw;
max-height: 100vh ;
}
.container{
display: flex;
max-height:100vh;
flex-direction: column;
flex-wrap: wrap;
align-content:flex-start;
}
.item1 {
background-color: red;
height: 200px;
flex: 1 0 150px;
}
.item2 {
background-color: blue;
height: 200px;
flex: 1 0 150px;
}
.item3 {
background-color: orange;
height: 200px;
flex: 1 0 150px;
}
I had a similar need and created a simple utility to achieve it.
- Demo at CodePen: https://codepen.io/hideya/pen/Jamabx
- GH gist: https://gist.github.com/hideya/16ed168a42f74eb5d2162b4e743940ff
The implementation is a bit wild and pretty much assumes no change in flex items except xy coords. You may need to adjust z-index, as it switches item's 'position' to 'absolute'.
Hope this helps.
window.addEventListener('load', function(event) {
var targetClassName = 'flex-wrap-anim';
var defaultDuration = '0.3s';
var dummyList = [];
function addDummy(item, duration) {
var top = item.offsetTop;
var left = item.offsetLeft;
setTimeout(function() {
item.style.position = 'absolute';
item.style.top = top + 'px';
item.style.left = left + 'px';
var dummyDiv = document.createElement('div');
dummyDiv.classList.add(targetClassName + '-dummy');
var rect = item.getBoundingClientRect();
dummyDiv.style.width = rect.width + 'px';
dummyDiv.style.height = rect.height + 'px';
dummyDiv.style.visibility = 'hidden';
dummyDiv['__' + targetClassName + '_pair'] = item;
dummyDiv['__' + targetClassName + '_duration'] = duration;
item.parentNode.appendChild(dummyDiv);
dummyList.push(dummyDiv);
}, 0);
}
var conts = document.getElementsByClassName(targetClassName);
for (var i = 0, max = conts.length; i < max; i++) {
var cont = conts[i];
cont.style.positoin = 'relative';
var duration = cont.getAttribute('data-duration')
|| defaultDuration;
var items = cont.getElementsByTagName('div');
for (var i = 0, max = items.length; i < max; i++) {
addDummy(items[i], duration);
}
}
window.addEventListener('resize', function(event) {
dummyList.forEach(function(dummyDiv) {
var item = dummyDiv['__' + targetClassName + '_pair'];
var duration = dummyDiv['__' + targetClassName + '_duration'];
if (item.offsetTop != dummyDiv.offsetTop) {
item.style.transition = 'all ' + duration;
item.style.top = dummyDiv.offsetTop + 'px';
item.style.left = dummyDiv.offsetLeft + 'px';
} else {
item.style.transition = '';
item.style.left = dummyDiv.offsetLeft + 'px';
}
});
});
});
While this cannot be done with CSS alone, you can accomplish this using JQuery. When looking at a flexbox using rows, the flexbox will change height if a new row is created or removed. Knowing this, we can add a .resize() function to the page to test if a window resize has altered the height of the flexbox. If it has, you can then execute an animation. I have created an example JFiddle here.
Here is the code that makes this work:
$(document).ready(function() {
var height = $('.container').css('height');
var id;
$(window).resize(function() {
clearTimeout(id);
id = setTimeout(doneResizing, 500);
});
function doneResizing() {
var newheight = $('.container').css('height');
if (newheight != height) {
$('.item').fadeOut();
$('.item').fadeIn();
height = newheight;
}
}
});
Now with a flexbox using columns, we need to detect when a change in width occurs. This is slightly more difficult as the flexbox width will take up the maximum allotted width as it is a block style element by default. So to accomplish this, you either need to set it as an inline flexbox using display: inline-flex, or set a maximum width for the flexbox equal to the width of its contents at its largest. Once you have set one of those, you can use the same code as above, except tweaking it to detect changes in width as opposed to height.
These changes applied an animation to all elements on resize. What if you want to only apply it to the element whose row/column changes? This would take more effort but is do-able. You would need to write many if-statements in your javascript/jquery code to catch which flex-item to apply the animation to based on width/height.

Youtube Background

I am trying to create a front-page with a Youtube video as a Background and a fixed transparent navigation. I have both but I want the video background to start at the very top of the page. Here is an example;
#bigvid{
https://jsfiddle.net/ackvq0x2/1/embedded/result/
How do get it done ?
Hi, you could use tubular: http://www.seanmccambridge.com/tubular/
as tubular is quite suffisticated, i extracted the necessary code
for you. (renders the video in full width and height, NOT stetched, similar to a css cover image)
html code:
<div id="player-container" style="overflow: hidden; position: absolute; width: 100%; height: 100%;">
<div id="player" style="position: absolute">
</div>
here comes the complete youtube API cover style stuff, extracted from
tubular. jquery is needed. Also the standard youtube html5 iframe api
code must be included - as given here:
https://developers.google.com/youtube/iframe_api_reference#Getting_Started
var ratio = 16 / 9;
window.onPlayerReady = function (e) {
resize();
}
$(window).on('resize', function () {
resize();
})
var resize = function () {
console.log("resize");
var heightcorrection = 0,
width = $(window).width(),
pWidth, // player width, to be defined
height = $(window).height() - heightcorrection,
pHeight, // player height, tbd
$videoPlayer = $('#player');
if (width / ratio < height) { // if new video height < window height (gap underneath)
pWidth = Math.ceil(height * ratio); // get new player width
$videoPlayer.width(pWidth).height(height).css({
left: (width - pWidth) / 2,
top: 0
}); // player width is greater, offset left; reset top
} else { // new video width < window width (gap to right)
pHeight = Math.ceil(width / ratio); // get new player height
$videoPlayer.width(width).height(pHeight).css({
left: 0,
top: (height - pHeight) / 2
}); // player height is greater, offset top; reset left
}
}

How can I make this canvas rectangle as sharp as a css div

My pen: http://codepen.io/anon/pen/mBliE
The orange css div with the same orange background and the same black border looks sharp and clean.
The orange rectangle drawn in a canvas looks blurry/distorted.
Why is there a difference? I do not set the canvas height/width with a css style which is a
beginner failure I have heard ;-)
How can I make my canvas sharp looking like css?
<canvas id="mycanvas" height="200" width="400"></canvas>
<div></div>
div{
border:black 2px solid;
height:198px;
width:50px;
background:orange;
display:inline-block;
}
canvas {
background: red;
}
$(document).ready(function() {
var canvas = document.getElementById("mycanvas");
var context = canvas.getContext("2d");
context.save();
context.lineWidth = 1;
context.fillStyle = "orange";
context.fillRect(348, 1, 50, 198);
context.strokeStyle = "black";
context.strokeRect(348, 1, 50, 198);
context.fill();
context.restore();
});
You could just play a little bit with you line width:
$(document).ready(function() {
var canvas = document.getElementById("mycanvas");
var context = canvas.getContext("2d");
context.save();
context.lineWidth = 2;
context.fillStyle = "orange";
context.fillRect(350, 1, 50, 198);
context.strokeStyle = "black";
context.strokeRect(349, 1, 50, 198);
context.fill();
context.restore();
});
CodePen
It looks like the stroke is centered on the canvas edges and not located inside or outside, and is set to two px in width as a minimum. By setting the stroke to two - context.lineWidth = 2; - the line gets sharper. Maybe you could somehow move the stroke outside or insede the canvas...
as Ken mentioned...

Making child element disappear on it's parent's `mouseleave`

I have a red div with green child, the green one moves when mouse hovers over it's parent. Pretty simple.
HTML:
<div class="big">
<div class="small"></div>
</div>
CSS:
.big {
position: relative;
width: 200px; height: 200px;
margin: 20px auto;
background: red;
}
.big:hover .small {
opacity: 1;
}
.small {
position: absolute;
top: 0; left: 0;
width: 50px; height: 50px;
background: green;
opacity: 0;
}
JavaScript:
$('.big').on('mousemove', function (e) {
var $this = $(this),
small = $this.find('.small'),
offset = $this.offset(),
cursorX = e.pageX - offset.left,
cursorY = e.pageY - offset.top,
smallX = cursorX - small.width() / 2,
smallY = cursorY - small.height() / 2;
$('.small').css({
top: smallY,
left: smallX
});
});
How to make the green box to disappear when it leaves the red one? :hover in css doesn't work because green div is part of the red one (I quess), so cursor never actually leaves it. Only when you move themouse really quickly the green div can't keep up with the cursor and disappers. Perhaps adding some wrapper elements with specific positioning will do the trick? Or something like jQuery stopPropagation()?
Here's my Fiddle
UPDATE: Here's updated code, based on suggestions from user nevermind. I added a transition, it disappears as I wanted it to, but now there's other problem. When cursor is moved outside the red box quickly, the green box stays at the border of it's parent.
I think this is what you want:
http://jsbin.com/obewaz/1/
http://jsbin.com/obewaz/1/edit
Same html/css, few additions in jquery:
$(document).ready(function() {
$('.big').on('mousemove', function (e) {
var $this = $(this),
smalle = $this.find('.small'),
offset = $this.offset(),
position=smalle.position(),
cursorX = e.pageX - offset.left,
cursorY = e.pageY - offset.top,
smallX = cursorX - smalle.width() / 2,
smallY = cursorY - smalle.height() / 2;
$('.small').css({
top: smallY,
left: smallX
});
console.log(position);
if(position.left<0 || position.left>150 || position.top<0 || position.top>150) {
$('.small').css('display','none');
}
else {
$('.small').css('display','block');
}
});
});
Of course, you can change/tweak values in last condition a little to fit your needs. Idea is: track position of small box, and when it is 'outside' of big box - hide it.
instead of mousemove try mouseover
DEMO

Centering a canvas

How do I markup a page with an HTML5 canvas such that the canvas
Takes up 80% of the width
Has a corresponding pixel height and width which effectively define the ratio (and are proportionally maintained when the canvas is stretched to 80%)
Is centered both vertically and horizontally
You can assume that the canvas is the only thing on the page, but feel free to encapsulate it in divs if necessary.
This will center the canvas horizontally:
#canvas-container {
width: 100%;
text-align:center;
}
canvas {
display: inline;
}
HTML:
<div id="canvas-container">
<canvas>Your browser doesn't support canvas</canvas>
</div>
Looking at the current answers I feel that one easy and clean fix is missing. Just in case someone passes by and looks for the right solution.
I am quite successful with some simple CSS and javascript.
Center canvas to middle of the screen or parent element. No wrapping.
HTML:
<canvas id="canvas" width="400" height="300">No canvas support</canvas>
CSS:
#canvas {
position: absolute;
top:0;
bottom: 0;
left: 0;
right: 0;
margin:auto;
}
Javascript:
window.onload = window.onresize = function() {
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth * 0.8;
canvas.height = window.innerHeight * 0.8;
}
Works like a charm - tested: firefox, chrome
fiddle: http://jsfiddle.net/djwave28/j6cffppa/3/
easiest way
put the canvas into paragraph tags like this:
<p align="center">
<canvas id="myCanvas" style="background:#220000" width="700" height="500" align="right"></canvas>
</p>
Tested only on Firefox:
<script>
window.onload = window.onresize = function() {
var C = 0.8; // canvas width to viewport width ratio
var W_TO_H = 2/1; // canvas width to canvas height ratio
var el = document.getElementById("a");
// For IE compatibility http://www.google.com/search?q=get+viewport+size+js
var viewportWidth = window.innerWidth;
var viewportHeight = window.innerHeight;
var canvasWidth = viewportWidth * C;
var canvasHeight = canvasWidth / W_TO_H;
el.style.position = "fixed";
el.setAttribute("width", canvasWidth);
el.setAttribute("height", canvasHeight);
el.style.top = (viewportHeight - canvasHeight) / 2;
el.style.left = (viewportWidth - canvasWidth) / 2;
window.ctx = el.getContext("2d");
ctx.clearRect(0,0,canvasWidth,canvasHeight);
ctx.fillStyle = 'yellow';
ctx.moveTo(0, canvasHeight/2);
ctx.lineTo(canvasWidth/2, 0);
ctx.lineTo(canvasWidth, canvasHeight/2);
ctx.lineTo(canvasWidth/2, canvasHeight);
ctx.lineTo(0, canvasHeight/2);
ctx.fill()
}
</script>
<body>
<canvas id="a" style="background: black">
</canvas>
</body>
in order to center the canvas within the window +"px" should be added to el.style.top and el.style.left.
el.style.top = (viewportHeight - canvasHeight) / 2 +"px";
el.style.left = (viewportWidth - canvasWidth) / 2 +"px";
Resizing canvas using css is not a good idea. It should be done using Javascript. See the below function which does it
function setCanvas(){
var canvasNode = document.getElementById('xCanvas');
var pw = canvasNode.parentNode.clientWidth;
var ph = canvasNode.parentNode.clientHeight;
canvasNode.height = pw * 0.8 * (canvasNode.height/canvasNode.width);
canvasNode.width = pw * 0.8;
canvasNode.style.top = (ph-canvasNode.height)/2 + "px";
canvasNode.style.left = (pw-canvasNode.width)/2 + "px";
}
demo here : http://jsfiddle.net/9Rmwt/11/show/
.
Simple:
<body>
<div>
<div style="width: 800px; height:500px; margin: 50px auto;">
<canvas width="800" height="500" style="background:#CCC">
Your browser does not support HTML5 Canvas.
</canvas>
</div>
</div>
</body>
Given that canvas is nothing without JavaScript, use JavaScript too for sizing and positionning (you know: onresize, position:absolute, etc.)
As to the CSS suggestion:
#myCanvas {
width: 100%;
height: 100%;
}
By the standard, CSS does not size the canvas coordinate system, it scales the content. In Chrome, the CSS mentioned will scale the canvas up or down to fit the browser's layout. In the typical case where the coordinate system is smaller than the browser's dimensions in pixels, this effectively lowers the resolution of your drawing. It most likely results in non-proportional drawing as well.
Same codes from Nickolay above, but tested on IE9 and chrome (and removed the extra rendering):
window.onload = window.onresize = function() {
var canvas = document.getElementById('canvas');
var viewportWidth = window.innerWidth;
var viewportHeight = window.innerHeight;
var canvasWidth = viewportWidth * 0.8;
var canvasHeight = canvasWidth / 2;
canvas.style.position = "absolute";
canvas.setAttribute("width", canvasWidth);
canvas.setAttribute("height", canvasHeight);
canvas.style.top = (viewportHeight - canvasHeight) / 2 + "px";
canvas.style.left = (viewportWidth - canvasWidth) / 2 + "px";
}
HTML:
<body>
<canvas id="canvas" style="background: #ffffff">
Canvas is not supported.
</canvas>
</body>
The top and left offset only works when I add px.
Make a line in the center and make it transparent.
This line will be the fulcrum to center the content in the canvas
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.strokeStyle = 'transparent';
context.moveTo(width/2, 0);
context.lineTo(width/2, height);
context.stroke();
context.textAlign = 'center';
with width height being the size of the html canvas
Wrapping it with div should work. I tested it in Firefox, Chrome on Fedora 13 (demo).
#content {
width: 95%;
height: 95%;
margin: auto;
}
#myCanvas {
width: 100%;
height: 100%;
border: 1px solid black;
}
And the canvas should be enclosed in tag
<div id="content">
<canvas id="myCanvas">Your browser doesn't support canvas tag</canvas>
</div>
Let me know if it works. Cheers.

Resources