How to build a drag scenario using CSS or JS - javascript

I'm trying to build a mechanic similar to this link https://demos.littleworkshop.fr/demos/infinitown/. Ignoring Three.JS's 3D features, I wish my user could drag the scene, this being an img tag or even a div with 3D transform, but the drag movement is just as smooth. How could I build this?
My first attempt https://codepen.io/diogenesjup-the-encoder/pen/xxdEoEg almost worked, however, the 3D transform, left the parent DIV and the drag movement is not so fluid.
#square {
position: absolute;
display: block;
top: 0;
left: 0;
width: 100px;
height: 100px;
background: #000;
z-index: 9999;
transform: rotateX( -70deg) rotateY( 14deg) rotateZ( 38deg) translateX(16px) translateY(-19px) translateZ(20px) scale(1) skewX( -19deg) skewY( 1deg);
overflow: auto;
transform-style: preserve-3d;
box-shadow: rgb(249 249 251) 1px 1px 0px 1px, rgb(34 33 81 / 1%) -1px 0px 28px 0px, rgb(34 33 81 / 25%) 28px 28px 28px 0px;
}
#map {
position: relative;
left: 0;
top: 0;
width: 200px;
height: auto;
transform: rotateX( -70deg) rotateY( 14deg) rotateZ( 38deg) translateX(16px) translateY(-19px) translateZ(20px) scale(1) skewX( -19deg) skewY( 1deg);
overflow: auto;
transform-style: preserve-3d;
box-shadow: rgb(249 249 251) 1px 1px 0px 1px, rgb(34 33 81 / 1%) -1px 0px 28px 0px, rgb(34 33 81 / 25%) 28px 28px 28px 0px;
}

For the inner div being out of bound issues add margin in the direction of the out of bounding in your case try adding margin-right: 35% for the #map div. For the smoothing behavior modify the ui.position property inside the drag callback. Keep on adjusting the added value to get the needed smoothing. (I subtracted 7 in both just as an example).
$("#map").draggable({
drag: function(event, ui) {
ui.position.left = ui.position.left-7;
ui.position.top = ui.position.top-7;
}
});

Related

How to animate the fill of an arc in CSS? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Is there a way we can fill color of css semi-circle in an incremental way in anticlockwise direction like a progress bar.
Here is the semi-circle code. https://jsfiddle.net/sonymax46/wqfovdjh/7/.
.cc{
background-color: transparent;
overflow: hidden;
width: 80px;
}
.curve {
height: 60px;
width: 100%;
background-color: none;
border-radius: 50%;
border: 2px solid blue;
transform: translateX(50%);
}
I want existing blue colour to be filled with Green on an event. How to achieve this with css O SVG
Thank in Advance
Option A is to use a container that cut's off a circular element and a pseudo-class as a "mask" over the top of the circle. Then a gradient background shows the other color when the element is rotated.
The major drawback to this is you have to have a solid color background that the overlay can match visually.
.wrapper {
margin: 20px;
width: 200px;
height: 200px;
overflow: hidden;
/* just to show the box could be transparent */
background-color: lightgray;
cursor: pointer;
}
.arc {
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
position: relative;
/* Use relative on parent so mask aligns */
left: 50%;
/* Move the circle 'outside' the wrapper */
background: linear-gradient(90deg, rgba(55, 238, 79, 1) 0%, rgba(55, 238, 79, 1) 50%, rgba(0, 212, 255, 1) 50%, rgba(0, 212, 255, 1) 100%);
transition: transform 1s ease;
}
.arc:after {
/* this creates the 'mask' */
content: '';
position: absolute;
width: 90%;
height: 90%;
top: 5%;
left: 5%;
background-color: white;
border-radius: 50%;
}
.wrapper:hover .arc {
/* rotate the full element because we can't transition backgrounds */
transform: rotate(-180deg);
}
.gradientExample {
/* just to show the gradient */
height: 20px;
width: 200px;
margin: 0 20px;
background: linear-gradient(90deg, rgba(55, 238, 79, 1) 0%, rgba(55, 238, 79, 1) 50%, rgba(0, 212, 255, 1) 50%, rgba(0, 212, 255, 1) 100%);
}
p {
font-family: Sans-Serif;
font-size: 14px;
margin: 20px 20px 0 20px;
}
<p>Hover over the arc</p>
<div class="wrapper">
<div class="arc"></div>
</div>
<div class="gradientExample"></div>
Option B - Use a clip-path instead of overlapping elements. This is much better but you need to create an SVG object to use for the arc and that's a pain from a sizing standpoint.
.wrapper {
margin: 20px;
width: 200px;
height: 200px;
overflow: hidden;
background-color: lightgray;
cursor: pointer;
}
.svgArc {
width: 100%;
height: 100%;
position: relative;
clip-path: url(#svgPath);
}
.svgArc:after {
/* have to use a pseudo element because we can't rotate the background */
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(90deg, rgba(55, 238, 79, 1) 0%, rgba(55, 238, 79, 1) 50%, rgba(0, 212, 255, 1) 50%, rgba(0, 212, 255, 1) 100%);
transition: transform 1s ease;
}
.v2:hover .svgArc:after {
transform: rotate(180deg);
}
p {
font-family: Sans-Serif;
font-size: 14px;
margin: 20px 20px 0 20px;
}
<p>Hover over the gray square</p>
<div class="wrapper v2">
<div class="svgArc">
</div>
</div>
<svg width="0" height="0" viewBox="0 0 200 200">
<defs>
<clipPath id="svgPath">
<path fill="#000000" stroke="#ffffff" stroke-width="1" d="M100,0 L100,10 L100,10 C50.2943725,10 10,50.2943725 10,100 C10,149.705627 50.2943725,190 100,190 L100,200 L100,200 C44.771525,200 0,155.228475 0,100 C0,44.771525 44.771525,0 100,0 Z"></path>
</clipPath>
</defs>
</svg>
Option C - Create an SVG circle and animate the offset-path. See my answer and example here: How to make linear css transition to SVG path?
maybe with css custom variables ?
const Root = document.documentElement
, btColor = document.getElementById('bt-color')
;
btColor.onclick=_=>
{
Root.style.setProperty('--bColor', 'green')
}
:root {
--bColor : blue;
}
.cc{
background-color: transparent;
overflow: hidden;
width: 80px;
}
.curve {
height: 60px;
width: 100%;
background-color: none;
border-radius: 50%;
border: 2px solid var(--bColor);
transform: translateX(50%);
}
<div class="cc">
<div class="curve"></div>
</div>
<br>
<button id="bt-color">change color</button>

Style an iframe's wrapper div without css clip-path

I want to find a replacement for CSS's clip-path to assure cross-browser compatibility with internet explorer, edge and safari for the following issue.
The following example shows what I want to do, an iframe component wrapped in a style div with variable border size:
I was able to somewhat replicate this style with clip-path using rotated squares at the cutted out corners and removed the "excess" square with clip-path as you can see in the following image of my component:
The problem arises when I test this component in internet edge, since the latter does not have support to clip-path the squares are never clipped and it appears as so:
As you can verify my styled wrapper is not even similar to the original example, also it does not work in all browsers...
So I am asking for some guidance in what I can do to make this styled div wrapper be supported in all browsers and be somewhat more similar to the original example.
I have read this can be done with :before and :after div compositions but that does not allow me to completely wrap the iframe component. Also, I have read about svg masking which can not also be used due the reason of the former.
Any help is appreciated.
.preview {
width: calc(100vw / 20);
height: calc(100vh / 10);
background: rgba(83, 80, 131, 0.5);
cursor: pointer;
clip-path: polygon( 10px 0%, 100% 0%, 100% 0%, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0% 100%, 0% 100%, 0% 10px);
}
.border-corner {
transition: all 0.2s ease-in;
background: #e9f396;
transform: rotate(45deg);
bottom: -15;
right: -15;
width: 30px;
height: 30px;
position: absolute;
}
<div class="preview center">
<img class="image" src="https://static.independent.co.uk/s3fs-public/thumbnails/image/2017/09/12/11/naturo-monkey-selfie.jpg?w968" />
</div>
<div class="border-corner"></div>
You can consider a pseudo element over the iframe that you style using multiple background:
.box {
display:inline-block;
background:blue;
position:relative;
}
.box:before {
content:"";
position:absolute;
top:20px;
left:20px;
bottom:20px;
right:20px;
background:
/*top left corner*/
linear-gradient(to top left ,transparent 49.8%,blue 50%) top left/30px 30px,
linear-gradient(to top left ,transparent 49.8%,grey 50%) top left/37px 37px,
/*bottom right corner*/
linear-gradient(to bottom right,transparent 49.8%,blue 50%) bottom right/30px 30px,
linear-gradient(to bottom right,transparent 49.8%,grey 50%) bottom right/50px 50px,
/*borders*/
linear-gradient(grey,grey) top /100% 5px,
linear-gradient(grey,grey) bottom /100% 5px,
linear-gradient(grey,grey) right /5px 100%,
linear-gradient(grey,grey) left /5px 100%;
background-repeat:no-repeat;
}
iframe {
display:block;
margin:20px;
background:red;
border:none;
}
<div class="box">
<iframe scr=""></iframe>
</div>
If you can use mask, you can get a CSS only solution. Please note: That excludes IE 10 and IE 11 and it only works in Edge 18+ (partially).
caniuse.com
However, without clip-path or mask, I highly doubt you will find a solution which makes it look equal in every browser while also allowing you to see what's in the background (assuming you want that element to be "floating" via absolute positioning or something alike). For non-supporting browsers, maybe you should consider having a "simple" box.
.shape {
position: relative;
width: 200px;
height: 200px;
background: #c00;
box-shadow: 0 0 0 5px #000 inset;
overflow: hidden;
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='47' height='49'%3E%3Cpath d='M11.23 0L0 11.23V49h35.77L47 37.77V0H11.23z'/%3E%3C/svg%3E") 0 0/200px 200px;
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='47' height='49'%3E%3Cpath d='M11.23 0L0 11.23V49h35.77L47 37.77V0H11.23z'/%3E%3C/svg%3E") 0 0/200px 200px;
}
.shape:before,
.shape:after {
content: '';
display: block;
position: absolute;
}
.shape:before {
top: 0;
left: 0;
border-style: solid;
border-width: 55px 55px 0 0;
border-color: #000 transparent transparent transparent;
}
.shape:after {
bottom: 0;
right: 0;
border-style: solid;
border-width: 0 0 70px 70px;
border-color: transparent transparent #000 transparent;
}
.shape_content {
display: block;
width: 100%;
height: 100%;
border: 0 none;
}
<div class="shape">
<iframe src="#foo" class="shape_content"></iframe>
</div>

How to have an animated gif during the page transition?

The project uses Backbone.js.
I tried doing it by appending a div with a gif to the html body.
startLoadingAnimation = function() {
$("<div id='loading'></div>").appendTo("body");
}
#loading {
display: block;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 0, 0, 0, .8 )
url('../img/loading.gif')
50% 50%
no-repeat;
}
It listens to an on-click event.
Everything goes as expected but the loading gif doesn't run the animation. I suspect it's because the browser is making a page request or something, so the gif doesn't run or stops running. Is there anyway around it, or a better way to put a "loading" animation in page transitions?
Any help or hint would be appreciated. Thanks in advance.
Did you try using css animation instead of loading an external resource ?
You can find many css spinners around the web like this one :
html,
body {
min-height: 100vh;
min-width: 100vw;
overflow: hidden;
margin: 0;
padding: 0;
}
.spinner-container {
display: block;
width: 100vw;
height: 100vh;
position: relative;
}
.spinner {
display: block;
width: 16px;
height: 16px;
border-radius: 16px;
position: absolute;
left: calc(50% - 8px);
top: calc(50% - 8px);
box-shadow: 20px 0px #FB404B, 0px 20px #FFA534, -20px 0px #87CB16, 0px -20px #1DC7EA;
transform: translatez(0px);
background: transparent;
animation: spin 1.2s infinite;
}
#keyframes spin {
0% {
box-shadow: 20px 0px #FB404B, 0px 20px #FFA534, -20px 0px #87CB16, 0px -20px #1DC7EA;
transform: rotate(0deg);
}
50% {
box-shadow: 40px 0px #FB404B, 0px 40px #FFA534, -40px 0px #87CB16, 0px -40px #1DC7EA;
}
100% {
transform: rotate(360deg);
}
}
<div class="spinner-container">
<div class="spinner"></div>
</div>

How to achieve unblur piece of image effect by mouse hover?

I need rounded unblur image effect by mouse hover on Image.
Like:
enter link description here (background)
Angular solution would be perfect, but jQuery or native JS is ok too. Any ideas ?
I've found solution below, but it is not work in some browsers (( In IE 11 image is not blurred.
$("body").on("mousemove", function(event) {
$("#blurarea").css({
top: event.clientY - 75,
left: event.clientX - 75
});
});
html, body { height: 100%; }
body { -webkit-transform: translate3D(0,0, 1px); }
.softarea {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url(http://blog.360cities.net/wp-content/uploads/2013/01/Omid.jpg) no-repeat;
-webkit-filter: blur(8px);
filter: grayscale(0.5) blur(10px);
/*firefox only*/
filter:url(#example);
}
.blurarea {
width: 150px;
height: 150px;
border: 1px solid #fff;
box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.85),
0 0 7px 7px rgba(0, 0, 0, 0.25),
inset 0 0 40px 2px rgba(0, 0, 0, 0.25);
background: url(http://blog.360cities.net/wp-content/uploads/2013/01/Omid.jpg) no-repeat;
background-attachment: fixed;
border-radius: 50%;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg">
<body>
<div id="softarea" class="softarea"></div>
<div id="blurarea" class="blurarea"></div>
<svg:svg>
<svg:filter id="example">
<svg:feGaussianBlur stdDeviation="2"/>
</svg:filter>
</svg:svg>
</body>
</html>

Mask animation with circular div in css

I am creating a google-material-design-like button with a ripple effect but my animation is showing up as a square shape when I want it to be circle.
This happens because the animation reaches a size bigger than the div it is in, and then fills the edges of the outer div making it look like a square. Is there a way to set the outer div itself to be a circle, because even though I've set border-radius: 50%, the div itself (not the shape created within the div) is still a square.
html:
<div id="imgs">
<div id="button"></div>
</div>
css:
#button{
position: relative;
overflow: hidden;
height: 56px;
width: 56px;
border-radius: 50%;
-webkit-box-shadow: 0px 1px 5px 0px rgba(50, 50, 50, 0.75);
-moz-box-shadow: 0px 1px 5px 0px rgba(50, 50, 50, 0.75);
box-shadow: 0px 1px 5px 0px rgba(50, 50, 50, 0.75);
}
.drop{
display: block;
position: absolute;
background: hsl(180, 40%, 80%);
border-radius: 50%;
transform: scale(0);
}
.drop.animate {
-webkit-animation-name: ripple;
-webkit-animation-duration: 0.65s;
-webkit-animation-timing-function: linear;
}
#-webkit-keyframes ripple {
100% {opacity: 0; transform: scale(2.5);}
}
I thought that giving the #button the property of overflow: hidden would create the masked effect, but it didn't.
javascript:
var parent, ink, d, x, y;## Heading ##
$("#imgs #button").click(function(e){
element = $(this);
if(element.find(".drop").length === 0)
element.prepend("<span class='drop'></span>");
drop = element.find(".drop");
drop.removeClass("animate");
if(!drop.height() && !drop.width())
{
d = Math.max(element.outerWidth(), element.outerHeight());
drop.css({height: d, width: d});
}
x = e.pageX - element.offset().left - drop.width()/2;
y = e.pageY - element.offset().top - drop.height()/2;
//set the position and add class .animate
drop.css({top: y+'px', left: x+'px'}).addClass("animate");
});
Here is a working fiddle where you can see the effect the above code generates. How can I alter it so that the ripple animation shows up round (confined to the round button) as opposed to squared (expanding over the button's boundaries)?
This issue is caused by a reported bug in chrome. There isn't a fix yet but there is a simple work-around that doesn't affect the aesthetic.
You need to add a transform to the element: -webkit-transform: rotate(0.000001deg); It can be so small as to be imperceptible, but that should be enough to fix it by promoting the paint order of the elements.
var parent, ink, d, x, y;
$("#imgs #button").click(function(e) {
element = $(this);
if (element.find(".drop").length === 0)
element.prepend("<span class='drop'></span>");
drop = element.find(".drop");
drop.removeClass("animate");
if (!drop.height() && !drop.width()) {
d = Math.max(element.outerWidth(), element.outerHeight());
drop.css({
height: d,
width: d
});
}
x = e.pageX - element.offset().left - drop.width() / 2;
y = e.pageY - element.offset().top - drop.height() / 2;
//set the position and add class .animate
drop.css({
top: y + 'px',
left: x + 'px'
}).addClass("animate");
});
#button {
position: relative;
overflow: hidden;
height: 56px;
width: 56px;
border-radius: 50%;
-webkit-box-shadow: 0 1px 5px 0 rgba(50, 50, 50, 0.75);
-moz-box-shadow: 0 1px 5px 0 rgba(50, 50, 50, 0.75);
box-shadow: 0 1px 5px 0 rgba(50, 50, 50, 0.75);
-webkit-transform: rotate(0.000001deg); /* This is the important bit */
}
.drop {
height: 56px;
width: 56px;
display: block;
position: absolute;
background: hsl(180, 40%, 80%);
border-radius: 90%;
transform: scale(0);
}
.drop.animate {
-webkit-animation-name: ripple;
-webkit-animation-duration: 0.65s;
-webkit-animation-timing-function: linear;
}
#-webkit-keyframes ripple {
100% {
opacity: 0;
transform: scale(2.5);
border-radius: 90%;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imgs">
<div id="button"></div>
</div>
Here is a breakdown of the bug:
https://code.google.com/p/chromium/issues/detail?id=157218

Categories