Placing two canvas elements on top of each other - javascript

I know this has been asked a few times already on SO (e.g.here), but I don't seem to be able to get this to work.
I'm trying to:
display images
place a canvas on top of each of them
get a user to draw on the top canvas based on the image underneath
get the data off all canvases to be stored locally.
I haven't been able to get the CSS to work so that the canvases are on top of each other and I've tried several ways of doing it.
HTML:
<div class="row">
<div class="pb-2 justify-content-center">
<h2><strong>Drawing test</strong></h2>
<div class="justify-content-center">
<form enctype="multipart/form-data" method="post" action="">{% csrf_token %}
<div class="wrapper">
<canvas id="dorsal" height="512" width="512"></canvas>
<canvas id="dorsal-duplicate" height="512" width="512"></canvas>
</div>
</form>
</div>
</div>
CSS
canvas {
position: absolute;
top: 0;
left: 0;
}
.wrapper {
position: relative;
width: 512px;
height: 512px;
}
.wrapper canvas {
position: absolute;
top: 0;
left: 0;
}
JS
var canvas1 = document.getElementById("dorsal"), ctx1 = canvas1.getContext("2d");
var canvas2 = document.getElementById("dorsal-duplicate"), ctx2 = canvas2.getContext("2d");
var background1 = new Image();
var to_draw_on = new Image();
background1.src = "{% static aspects.Dorsal.0 %}"; /* image from Django static folder */
background1.onload = function(){ctx1.drawImage(background1,0,0);}
to_draw_on.onload = function(){ctx2.drawImage(to_draw_on,0,0);}
/* code to draw on the second canvas */
This only results in the second canvas being beneath the first canvas, so that when I go to draw, I won't be able to trace the outline of the object.

Actually I am not sure why your version does not work (it should as-is!), but here's a version that uses your code and a bit of CSS to check the overlap. Read the comments in the CSS. When done, remove the extra code and enable .wrapper canvas { top: 0 } again.
Without the Javascript, I might add, I don't use Django.
However, it seems your JS new Image() has no size parameters and ctx.drawimage only has a location (0,0) but no (height,width) to work with.
So, height=0, width=0 yields nothing to overlap...
Forgot to mention: give both canvas a z-index so you can control which is on top.
UPDATE
Added Javascript and a third canvas to prove the code works as expected. Also inserted z-index per canvas as suggested before. Retrieving a few random pics from 'Lorem Picsum' to fill the canvas.
NOTICE that I use proper width/height parameters in my Javascript....
var canvas1 = document.getElementById("dorsal") , ctx1 = canvas1.getContext("2d");
var canvas2 = document.getElementById("dorsal-duplicate"), ctx2 = canvas2.getContext("2d");
var canvas3 = document.getElementById("extra-img") , ctx3 = canvas3.getContext("2d");
var background1 = new Image(512,256);
var to_draw_on = new Image(512,256);
var extra_img = new Image(512,256);
background1.src = "https://picsum.photos/512/512?random=0";
to_draw_on.src = "https://picsum.photos/512/512?random=1";
extra_img.src = "https://picsum.photos/512/512?random=2";
background1.onload = function(){ctx1.drawImage(background1,0,0);}
to_draw_on.onload = function(){ctx2.drawImage(to_draw_on,0,0);}
extra_img.onload = function(){ctx3.drawImage(extra_img,0,0);}
/* code to draw on the second canvas */
.wrapper {
position: relative;
width : 512px;
height: 512px;
}
.wrapper canvas {
position: absolute;
left: 0;
/* top : 0; /* temporary disabled */
/*ADDED*/
width: 100%; height: 100%; /* fill-parent */
border: 2px dotted black;
}
/*
To check the overlap:
- make #dorsal fill the top half of 512px
- make #dorsal-duplicate fill the bottom half of 512px
*/
#dorsal {
top : 0;
height: 50%;
background-color: green;
z-index: 1;
}
#dorsal-duplicate {
background-color: red;
bottom: 0;
height: 50%;
z-index: 2;
}
#extra-img {
background-color: blue;
left: 64px; bottom: 128px;
height: 50%; width: 75%;
z-index: 3;
}
<div class="wrapper">
<div class="pb-2 justify-content-center">
<h2>
<strong>Drawing test</strong>
</h2>
<p>removed width/height values from <canvas>, redundant.
<div class="justify-content-center">
<form enctype="multipart/form-data" method="post" action="">{% csrf_token %}
<div class="wrapper">
<canvas id="dorsal" ></canvas>
<canvas id="dorsal-duplicate"></canvas>
<canvas id="extra-img" ></canvas>
</div>
</form>
</div>
</div>
</div>

usage of static template tag is
{% static 'static_file_here.extension' %}
so basically the code background1.src = "{% static aspects.Dorsal.0 %}";
should be background1.src = "{% static 'aspects.Dorsal.0' %}";

Related

CSS position elements along ring of a circle [duplicate]

How can I position several <img> elements into a circle around another and have those elements all be clickable links as well? I want it to look like the picture below, but I have no idea how to achieve that effect.
Is this even possible?
2020 solution
Here's a more modern solution I use these days.
I start off by generating the HTML starting from an array of images. Whether the HTML is generated using PHP, JS, some HTML preprocessor, whatever... this matters less as the basic idea behind is the same.
Here's the Pug code that would do this:
//- start with an array of images, described by url and alt text
- let imgs = [
- {
- src: 'image_url.jpg',
- alt: 'image alt text'
- } /* and so on, add more images here */
- ];
- let n_imgs = imgs.length;
- let has_mid = 1; /* 0 if there's no item in the middle, 1 otherwise */
- let m = n_imgs - has_mid; /* how many are ON the circle */
- let tan = Math.tan(Math.PI/m); /* tangent of half the base angle */
.container(style=`--m: ${m}; --tan: ${+tan.toFixed(2)}`)
- for(let i = 0; i < n_imgs; i++)
a(href='#' style=i - has_mid >= 0 ? `--i: ${i}` : null)
img(src=imgs[i].src alt=imgs[i].alt)
The generated HTML looks as follows (and yes, you can write the HTML manually too, but it's going to be a pain to make changes afterwards):
<div class="container" style="--m: 8; --tan: 0.41">
<a href='#'>
<img src="image_mid.jpg" alt="alt text"/>
</a>
<a style="--i: 1">
<img src="first_img_on_circle.jpg" alt="alt text"/>
</a>
<!-- the rest of those placed on the circle -->
</div>
In the CSS, we decide on a size for the images, let's say 8em. The --m items are positioned on a circle and it's if they're in the middle of the edges of a polygon of --m edges, all of which are tangent to the circle.
If you have a hard time picturing that, you can play with this interactive demo which constructs the incircle and circumcircle for various polygons whose number of edges you pick by dragging the slider.
This tells us that the size of the container must be twice the radius of the circle plus twice half the size of the images.
We don't yet know the radius, but we can compute it if we know the number of edges (and therefore the tangent of half the base angle, precomputed and set as a custom property --tan) and the polygon edge. We probably want the polygon edge to be a least the size of the images, but how much we leave on the sides is arbitrary. Let's say we have half the image size on each side, so the polygon edge is twice the image size. This gives us the following CSS:
.container {
--d: 6.5em; /* image size */
--rel: 1; /* how much extra space we want between images, 1 = one image size */
--r: calc(.5*(1 + var(--rel))*var(--d)/var(--tan)); /* circle radius */
--s: calc(2*var(--r) + var(--d)); /* container size */
position: relative;
width: var(--s); height: var(--s);
background: silver /* to show images perfectly fit in container */
}
.container a {
position: absolute;
top: 50%; left: 50%;
margin: calc(-.5*var(--d));
width: var(--d); height: var(--d);
--az: calc(var(--i)*1turn/var(--m));
transform:
rotate(var(--az))
translate(var(--r))
rotate(calc(-1*var(--az)))
}
img { max-width: 100% }
See the old solution for an explanation of how the transform chain works.
This way, adding or removing an image from the array of images automatically arranges the new number of images on a circle such that they're equally spaced out and also adjusts the size of the container. You can test this in this demo.
OLD solution (preserved for historical reasons)
Yes, it is very much possible and very simple using just CSS. You just need to have clear in mind the angles at which you want the links with the images (I've added a piece of code at the end just for showing the angles whenever you hover one of them).
You first need a wrapper. I set its diameter to be 24em (width: 24em; height: 24em; does that), you can set it to whatever you want. You give it position: relative;.
You then position your links with the images in the center of that wrapper, both horizontally and vertically. You do that by setting position: absolute; and then top: 50%; left: 50%; and margin: -2em; (where 2em is half the width of the link with the image, which I've set to be 4em - again, you can change it to whatever you wish, but don't forget to change the margin in that case).
You then decide on the angles at which you want to have your links with the images and you add a class deg{desired_angle} (for example deg0 or deg45 or whatever). Then for each such class you apply chained CSS transforms, like this:
.deg{desired_angle} {
transform: rotate({desired_angle}) translate(12em) rotate(-{desired_angle});
}
where you replace {desired_angle} with 0, 45, and so on...
The first rotate transform rotates the object and its axes, the translate transform translates the object along the rotated X axis and the second rotate transform brings back the object into position.
The advantage of this method is that it is flexible. You can add new images at different angles without altering the current structure.
CODE SNIPPET
.circle-container {
position: relative;
width: 24em;
height: 24em;
padding: 2.8em;
/*2.8em = 2em*1.4 (2em = half the width of a link with img, 1.4 = sqrt(2))*/
border: dashed 1px;
border-radius: 50%;
margin: 1.75em auto 0;
}
.circle-container a {
display: block;
position: absolute;
top: 50%; left: 50%;
width: 4em; height: 4em;
margin: -2em;
}
.circle-container img { display: block; width: 100%; }
.deg0 { transform: translate(12em); } /* 12em = half the width of the wrapper */
.deg45 { transform: rotate(45deg) translate(12em) rotate(-45deg); }
.deg135 { transform: rotate(135deg) translate(12em) rotate(-135deg); }
.deg180 { transform: translate(-12em); }
.deg225 { transform: rotate(225deg) translate(12em) rotate(-225deg); }
.deg315 { transform: rotate(315deg) translate(12em) rotate(-315deg); }
<div class='circle-container'>
<a href='#' class='center'><img src='image.jpg'></a>
<a href='#' class='deg0'><img src='image.jpg'></a>
<a href='#' class='deg45'><img src='image.jpg'></a>
<a href='#' class='deg135'><img src='image.jpg'></a>
<a href='#' class='deg180'><img src='image.jpg'></a>
<a href='#' class='deg225'><img src='image.jpg'></a>
<a href='#' class='deg315'><img src='image.jpg'></a>
</div>
Also, you could further simplify the HTML by using background images for the links instead of using img tags.
EDIT: example with fallback for IE8 and older (tested in IE8 and IE7)
Here is the easy solution without absolute positioning:
.container .row {
margin: 20px;
text-align: center;
}
.container .row img {
margin: 0 20px;
}
<div class="container">
<div class="row">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
</div>
<div class="row">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
</div>
<div class="row">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
</div>
</div>
http://jsfiddle.net/mD6H6/
Using the solution proposed by #Ana:
transform: rotate(${angle}deg) translate(${radius}px) rotate(-${angle}deg)
I created the following jsFiddle that places circles dynamically using plain JavaScript (jQuery version also available).
The way it works is rather simple:
document.querySelectorAll( '.ciclegraph' ).forEach( ( ciclegraph )=>{
let circles = ciclegraph.querySelectorAll( '.circle' )
let angle = 360-90, dangle = 360 / circles.length
for( let i = 0; i < circles.length; ++i ){
let circle = circles[i]
angle += dangle
circle.style.transform = `rotate(${angle}deg) translate(${ciclegraph.clientWidth / 2}px) rotate(-${angle}deg)`
}
})
.ciclegraph {
position: relative;
width: 500px;
height: 500px;
margin: calc(100px / 2 + 0px);
}
.ciclegraph:before {
content: "";
position: absolute;
top: 0; left: 0;
border: 2px solid teal;
width: calc( 100% - 2px * 2);
height: calc( 100% - 2px * 2 );
border-radius: 50%;
}
.ciclegraph .circle {
position: absolute;
top: 50%; left: 50%;
width: 100px;
height: 100px;
margin: calc( -100px / 2 );
background: teal;
border-radius: 50%;
}
<div class="ciclegraph">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
Building off #Ana's excellent answer, I created this dynamic version that allows you to add and remove elements from the DOM and maintain proportionate spacing between the elements - check out my fiddle: https://jsfiddle.net/skwidbreth/q59s90oy/
var list = $("#list");
var updateLayout = function(listItems) {
for (var i = 0; i < listItems.length; i++) {
var offsetAngle = 360 / listItems.length;
var rotateAngle = offsetAngle * i;
$(listItems[i]).css("transform", "rotate(" + rotateAngle + "deg) translate(0, -200px) rotate(-" + rotateAngle + "deg)")
};
};
$(document).on("click", "#add-item", function() {
var listItem = $("<li class='list-item'>Things go here<button class='remove-item'>Remove</button></li>");
list.append(listItem);
var listItems = $(".list-item");
updateLayout(listItems);
});
$(document).on("click", ".remove-item", function() {
$(this).parent().remove();
var listItems = $(".list-item");
updateLayout(listItems);
});
#list {
background-color: blue;
height: 400px;
width: 400px;
border-radius: 50%;
position: relative;
}
.list-item {
list-style: none;
background-color: red;
height: 50px;
width: 50px;
position: absolute;
top: 50%;
left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<ul id="list"></ul>
<button id="add-item">Add item</button>
Here is a version I made in React from the examples here.
CodeSandbox Example
import React, { useRef, useEffect } from "react";
import "./styles.css";
export default function App() {
const graph = useRef(null);
useEffect(() => {
const ciclegraph = graph.current;
const circleElements = ciclegraph.childNodes;
let angle = 360 - 90;
let dangle = 360 / circleElements.length;
for (let i = 0; i < circleElements.length; i++) {
let circle = circleElements[i];
angle += dangle;
circle.style.transform = `rotate(${angle}deg) translate(${ciclegraph.clientWidth /
2}px) rotate(-${angle}deg)`;
}
}, []);
return (
<div className="App">
<div className="ciclegraph" ref={graph}>
<div className="circle" />
<div className="circle" />
<div className="circle" />
<div className="circle" />
<div className="circle" />
<div className="circle" />
</div>
</div>
);
}
You can certainly do it with pure css or use JavaScript. My suggestion:
If you already know that the images number will never change just calculate your styles and go with plain css (pros: better performances, very reliable)
If the number can vary either dynamically in your app or just may vary in the future go with a Js solution (pros: more future-proof)
I had a similar job to do, so I created a script and open sourced it here on Github for anyone who might need it. It just accepts some configuration values and simply outputs the CSS code you need.
If you want to go for the Js solution here's a simple pointer that can be useful to you. Using this html as a starting point being #box the container and .dot the image/div in the middle you want all your other images around:
Starting html:
<div id="box">
<div class="dot"></div>
<img src="my-img.jpg">
<!-- all the other images you need-->
</div>
Starting Css:
#box{
width: 400px;
height: 400px;
position: relative;
border-radius: 100%;
border: 1px solid teal;
}
.dot{
position: absolute;
border-radius: 100%;
width: 40px;
height: 40px;
left: 50%;
top: 50%;
margin-left: -20px;
margin-top: -20px;
background: rebeccapurple;
}
img{
width: 40px;
height: 40px;
position: absolute;
}
You can create a quick function along these lines:
var circle = document.getElementById('box'),
imgs = document.getElementsByTagName('img'),
total = imgs.length,
coords = {},
diam, radius1, radius2, imgW;
// get circle diameter
// getBoundingClientRect outputs the actual px AFTER transform
// using getComputedStyle does the job as we want
diam = parseInt( window.getComputedStyle(circle).getPropertyValue('width') ),
radius = diam/2,
imgW = imgs[0].getBoundingClientRect().width,
// get the dimensions of the inner circle we want the images to align to
radius2 = radius - imgW
var i,
alpha = Math.PI / 2,
len = imgs.length,
corner = 2 * Math.PI / total;
// loop over the images and assign the correct css props
for ( i = 0 ; i < total; i++ ){
imgs[i].style.left = parseInt( ( radius - imgW / 2 ) + ( radius2 * Math.cos( alpha ) ) ) + 'px'
imgs[i].style.top = parseInt( ( radius - imgW / 2 ) - ( radius2 * Math.sin( alpha ) ) ) + 'px'
alpha = alpha - corner;
}
You can see a live example here
There is no way to magically place clickable items in a circle around another element with CSS.
The way how I would do this is by using a container with position:relative;. And then place all the elements with position:absolute; and using top and left to target it's place.
Even though you haven't placed jquery in your tags it might be best to use jQuery / javascript for this.
First step is placing your center image perfectly in the center of the container using position:relative;.
#centerImage {
position:absolute;
top:50%;
left:50%;
width:200px;
height:200px;
margin: -100px 0 0 -100px;
}
After that you can place the other elements around it by using an offset() of the centerImage minus the offset() of the container. Giving you the exact top and left of the image.
var left = $('#centerImage').offset().left - $('#centerImage').parent().offset().left;
var top = $('#centerImage').offset().top - $('#centerImage').parent().offset().top;
$('#surroundingElement1').css({
'left': left - 50,
'top': top - 50
});
$('#surroundingElement2').css({
'left': left - 50,
'top': top
});
$('#surroundingElement3').css({
'left': left - 50,
'top': top + 50
});
What I've done here is placing the elements relative to the centerImage. Hope this helps.
You could do it like this: fiddle
Don't mind the positioning, its a quick example
The first step is to have 6 long columnar boxes:
The second step is to use position: absolute and move them all into the middle of your container:
And now rotate them around the pivot point located at the bottom center. Use :nth-child to vary rotation angles:
div {
transform-origin: bottom center;
#for $n from 0 through 7 {
&:nth-child(#{$n}) {
rotate: (360deg / 6) * $n;
}
}
Now all you have to do is to locate your images at the far end of every column, and compensate the rotation with an anti-rotation :)
Full source:
<div class="flower">
<div class="petal">1</div>
<div class="petal">2</div>
<div class="petal">3</div>
<div class="petal">4</div>
<div class="petal">5</div>
<div class="petal">6</div>
</div>
.flower {
width: 300px;
height: 300px;
// We need a relative position
// so that children can have "position:abolute"
position: relative;
.petal {
// Make sure petals are visible
border: 1px solid #999;
// Position them all in one point
position: absolute; top: 0; left: 50%;
display: inline-block;
width: 30px; height: 150px;
// Rotation
transform-origin: bottom center;
#for $n from 0 through 7 {
&:nth-child(#{$n}) {
// Petal rotation
$angle: (360deg / 6) * $n;
rotate: $angle;
// Icon anti-rotation
.icon { rotate: -$angle; }
}
}
}
}
See CodePen

Change image opacity when using GetElementById

Part of my Uni module requires me to make a webstory that uses random elements to mix up the story. I'm using GetElementById in JS to embed one random image from an array into a div, which works perfectly fine. The image becomes the background of the div, and I then have text on top of the image - again this all works perfectly fine.
However the issue is that I want the image to be slightly transparent so that the text is easier to read, however no matter what solution I try, I can't get it to work.
I've tried making the div transparent in both CSS and JS, however then the whole div including the text is effected which defeats the point. Then when I try the RGBA style in CSS, the image isn't effected.
So what I need is the image that is loaded into the div through JS to be slightly transparent, whilst the text that is also in the div in the HTML doument to remain untouched.
This is the JS I'm using to randomly select an image:
function randomGun() {
var imgCount = 3;
var dir = 'img/';
var randomCount = Math.round(Math.random() * (imgCount - 1)) + 1;
var images = new Array
images[1] = "gun1.jpg",
images[2] = "gun2.jpg",
images[3] = "gun3.jpg",
document.getElementById("left").style.backgroundImage = "url(" + dir + images[randomCount] + ")";
}
<div id="container">
<div id="left">
<a id="message">Drive a bit closer to see if anybody is there.</a>
</div>
<script>
window.onload = randomGun()
</script>
</div>
Use a nested div with semi-transparent white background.
<div id="container">
<div id="left">
<div id="nested" style="width:100%;height:100%; background-color: rgba(255,255,255,0.5)">
<a id="message">Drive a bit closer to see if anybody is there.</a>
</div>
</div>
<script>window.onload = randomGun()</script>
</div>
In addition, I would set everything relative to style in a stylesheet, or at least inside a <style></style>.
UPDATE
Added your JS and fixed it a little. Note the adjustment to the random expression.
Perhaps this'll help you.
Use an element that'll contain 2 other elements, give the container position:relative and z-index:-2
Then the 2 elements inside should have position:absolute.
Next give the top element z-index:-1, background:url(http://image-host.com/path/to/img.jpg), and opacity:.5
Then the second element should have text and whatever else you want visible. Give this element z-index:1.
The reason why opacity wasn't working the way you expected to work is because opacity applies to everything within the element as well. Here in the Snippet, we layered an element with content and an element with a background image separately.
REFERENCE: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index
SNIPPET
function randomBG() {
var imgCount = 3;
var path = 'http://imgh.us/';
var randomCount = Math.round(Math.random() * (imgCount));
var images = ['solar_system.jpg', 'kowloon.jpg', 'transparent-map.png'];
document.getElementById("fader").style.backgroundImage = "url(" + path + images[randomCount] + ")";
}
window.onload = randomBG;
html,
body {
height: 100%;
width: 100%;
font: 400 16px/1.5 Verdana;
box-sizing: border-box;
}
* {
margin: 0;
padding: 0;
border: 0;
}
#base {
position: relative;
z-index: -2;
width: 100vw;
height: 100vh;
}
#content {
position: absolute;
z-index: 1;
padding: 20px;
margin: 0 auto;
width: 75%;
height: auto;
top: 0;
left: 0;
background: none;
}
#fader {
position: absolute;
z-index: -1;
padding: 20px;
margin: 0 auto;
min-width: 75%;
min-height: 75%;
/*background: url(http://imgh.us/Lenna.png);*/
opacity: .5;
}
<main id='base'>
<section id='fader'></section>
<article id='content'>
<h1>This is the Text</h1>
</article>
</main>

Trying to create a div with resizable dragger

I'm pretty sure there is already an example for this but I couldn't find one, and I don't know exactly what to search for.
http://imgur.com/a/hHNkZ
I am trying to make a resizable div from the button circled in red above.
The photo behind this div comes from a slick slider ( http://kenwheeler.github.io/slick/ ).
<div class="slider-for">
<img src="images/product0.jpg" alt="">
<img src="images/product1.jpg" alt="">
<img src="images/product2.jpg" alt="">
<img src="images/product3.jpg" alt="">
</div>
I was thinking of making a width 0 div above, and then with the slider, increase its width with js maybe.
In this div, I want to put a recipe for that certain product. I have 4 photos, so the content has to change depending on picture. ( so it's not static content).
Does this need to be made in php?
I think this would be helpful to you:
https://jsfiddle.net/u0Ljnttg/1/
Its little bit complicated, but still good enough. :)
Just for sake of SO:
JS:
var links = document.getElementById("imageLinks");
links.onmousedown = function(e) {
var theSrc = e.target.dataset.src;
if (theSrc) {
str = "url(\"" + theSrc + "\");";
//Sorry for using this:
document.getElementById("imageBack").setAttribute("style", "background-image:" + str)
}
}
var resizer = document.getElementById("content-resize");
resizer.onmousedown = resizableStart;
function resizableStart(e) {
var elem = document.getElementById("content");
elem.originalW = elem.clientWidth;
this.onmousemove = resizableCheck;
this.onmouseup = this.onmouseout = resizableEnd;
}
function resizableCheck(e) {
var elem = document.getElementById("content");
if (elem.clientWidth === elem.originalW) {
elem.originalX = e.clientX;
this.onmousemove = resizableMove;
}
}
function resizableMove(e) {
var elem = document.getElementById("content");
var newW = elem.originalW - e.clientX + elem.originalX;
if (newW < elem.originalW) {
elem.style.width = newW + 'px';
}
}
function resizableEnd() {
this.onmousemove = this.onmouseout = this.onmouseup = null;
}
HTML:
<div class='container'>
<div class='images' id="imageBack" style="background-image: url('http://data.whicdn.com/images/20948152/large.png')">
<div class='content' id="content">
<div id="imageLinks">
<a href="#" data-src='http://ichef.bbci.co.uk/news/660/cpsprodpb/1325A/production/_88762487_junk_food.jpg'>1</a>
<a href="#" data-src='http://i.imgur.com/NhDejjN.jpg'>2</a>
<a href="#" data-src='https://s-media-cache-ak0.pinimg.com/564x/80/40/9d/80409d8c06d21e0c0416a40c2176def3.jpg'>3</a>
<a href="#" data-src='http://data.whicdn.com/images/20948152/large.png'>4</a>
</div>
<span id="content-resize"></span>
</div>
</div>
</div>
CSS:
html,
body {
min-height: 100% !important;
height: 100%;
}
.container {
width: 100%;
min-height: 100%;
height: 100%;
}
.images {
width: 100%;
min-height: 100% !important;
height: 100%;
}
#content {
min-height: 100% !important;
height: 100%;
/*Change this to change width*/
width: 70%;
resize: horizontal;
float: right;
position: relative;
background: white;
}
div {
border: 1px solid black;
}
span {
border: 1px solid black;
border-radius: 50%;
position: absolute;
top: calc(50% - 20px);
left: -10px;
cursor: pointer;
height: 40px;
width: 40px;
display: inline-block;
background: white;
}
I am not sure if you already solved this issue, but since you helped me on the other question, I am interested in helping you with this.
You have some options.
Use pure JavaScript. You can use a lib (eg: this) for that.
Use Jquery $().draggable() propriety. This might help for styling the button..
Using pure HTML & CSS resize. This is not good, since you cannot apply any style to the <div>.
You can make a workaround mixing three <div> elements,
One of them with position: fixed. This is your background.
Another for the container (with a width set manually to hide the page from user). Remove the scrollbar and force the width of your html, body to match your screen.
Another <div> inside the container for your content. This should be able to move horizontally to show and hide the elements.

Hover over an element covered by another element's padding

So I have a map composed by tiles that are svg elements.
In the image, the tile itself is the blue area, but it has a buffer area to allow geometries that span outside the tile to render whole. The problem is that this buffer area (in green), is covering the geometries from other tiles that are below it. This buffer zone is set in CSS as the following:
padding: 128px;
margin: -128px;
Is there a way to hover/click "through" the buffer area, or is there a better approach in CSS to achieve this?
Padding is part of a element, therefore will react like it was content of your tag.
See here. If you absolutely need to have that spacing to be padding, you can't click anything behind neither content nor padding.
You might consider changing your layering, using z-index, but for further advise on this, you'll have to provide further code, your HTML Markup and CSS code.
If that blue thingy is the only element that needs this treatment, then I suggest creating a key bind to move that element to the back with z-index, and be done with it.
If you require this functionality on all of these red balls, the thing to do would probably be to move, the one you click on, to the back with z-index ( again ).
Both of these require you to use JavaScript most likely, unless you want to move that big blue element to the back on hover.
To always move the clicked element to the back you could just keep track of what was the last assigned z-index, and decrease it by one every time you assign it to a new object.
Something like this would probably do:
#box1 { position: absolute; background-color: #123; width: 100px; height: 100px; top: 200px; left: 300px; opacity: 0.9; }
#box2 { position: absolute; background-color: #ABC; width: 100px; height: 100px; top: 250px; left: 350px; opacity: 0.8; }
<div class="box" id="box1"></div>
<div class="box" id="box2"></div>
<script type="text/javascript">
var boxes = document.getElementsByClassName("box");
var length = boxes.length;
var index = 0;
function moveToBack(event)
{
var element = this;
this.style.zIndex = index;
index--;
return false;
}
for(var i = 0; i < length; i++)
{
var box = boxes[i];
box.addEventListener("click", moveToBack, false);
}
</scirpt>
Does that do the job ? or did you mean something else entirely ?
Only way I can seem to get it to work is to add a child inner element and give pointer-events:none to the wrapper and pointer-events:auto to the inner child element. It's not ideal as support for pointer-events is limited and there's no telling if all browsers will respect a child of pointer-events:none element having a different value than its parent. It will need tested. Well, in any case, here is the code:
$('.tile').on('mouseenter', function(){
$('.info', this).find('.tile-info').remove();
var ts = new Date().getTime();
$('.info', this).append('<div class="tile-info">mouseenter tile '+ts+'</div>');
});
$('.tile').on('mouseleave', function(){
$('.info', this).find('.tile-info').remove();
var ts = new Date().getTime();
$('.info', this).append('<div class="tile-info">mouseleave tile '+ts+'</div>');
});
$('.inner').on('mouseenter', function(){
$('.info', this).find('.inner-info').remove();
var ts = new Date().getTime();
$('.info', this).append('<div class="inner-info">mouseenter inner '+ts+'</div>');
});
$('.inner').on('mouseleave', function(){
$('.info', this).find('.inner-info').remove();
var ts = new Date().getTime();
$('.info', this).append('<div class="inner-info">mouseleave inner '+ts+'</div>');
});
.tile {
width: 200px;
height: 200px;
background: rgba(100,100,200,0.2);
padding: 50px;
margin: -50px;
position: absolute;
pointer-events:none;
}
.tile:nth-of-type(1) {left: 300px;top: 20px;}
.tile:nth-of-type(2) {left: 90px;top: 210px;}
.tile:nth-of-type(3) {left: 0px;top: 0px;}
.tile:nth-of-type(4) {left: 360px;top: 240px;}
.tile .inner {
width: 100%;
height: 100%;
background: rgba(200,100,100,0.2);
pointer-events:auto;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tile">
<div class="inner">
<div class="info"></div>
</div>
</div>
<div class="tile">
<div class="inner">
<div class="info"></div>
</div>
</div>
<div class="tile">
<div class="inner">
<div class="info"></div>
</div>
</div>
<div class="tile">
<div class="inner">
<div class="info"></div>
</div>
</div>

Add element on top of image dynamically

When I click the button, it has to add an object (img, p) inside the div and the image with border and then take the position of that object, (x, y coordinates).
How can I make this using JQuery?
HTML:
<div style="height: 440px; border: 1px solid; width: 880px; margin-top: 50px; margin-left: -12px;">
<img id="imagem-principal" width="880" height="440" class="custom_media_image attachment-post-thumbnail" src="<?= $segunda_imagem; ?>">
</div>
To have a button create a new <img> and place it on top, add the following styles:
div {
position: relative;
}
img:not(#imagem-principal) {
position: absolute;
}
Then, you can add an onclick listener in jQuery:
$("#addImg").click(function() {
// set x and y to what you want
var xCoor = // X_COORDINATE;
var yCoor = // Y_COORDINATE;
var newImg = $("<img src='/* IMAGE_URL */' />");
newImg.css({left: xCoor, top: yCoor});
$("div").append(newImg);
});
This will create a new image with the given x and y coordinates on top of the other image.
See working example on JSFiddle.net.

Categories

Resources