I have a svg image with a mouse hover on four rect elements and an accordion with four buttons done with javascript. I want to connect each element by hovering them simultaneously (a rect and button accordion) and by clicking on a svg rect it will open a button accordion and by clicking on an accordion it will fill a rect. You can check my fiddle here: https://jsfiddle.net/pfrutuoso/zcsj8g05/2/
This is my html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div class="wrapper">
<div class="stage_info">
<button class="accordion">Stage 1</button>
<div class="panel">
<p>Information here..</p>
</div>
<button class="accordion">Stage 2</button>
<div class="panel">
<p>Information here..</p>
</div>
<button class="accordion">Stage 3</button>
<div class="panel">
<p>Information here..</p>
</div>
<button class="accordion">Stage 4</button>
<div class="panel">
<p>Information here..</p>
</div>
</div>
<div class="stage_img">
<map id="big_stage">
<svg version="1.1" id="stadium" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="100%" height="100%" viewBox="0 0 456.122 451.02" enable-background="new 0 0 456.122 451.02"
xml:space="preserve">
<rect id="stage4" x="25.51" y="25.51" fill="#1C6131" width="200" height="200"/>
<rect id="stage3" x="230.612" y="25.51" fill="#1C6131" width="200" height="200"/>
<rect id="stage2" x="25.51" y="229.592" fill="#1C6131" width="200" height="200"/>
<rect id="stage1" x="230.612" y="229.592" fill="#1C6131" width="200" height="200"/>
</svg>
</map>
</div>
</div>
</body>
</html>
My css:
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
transition: 0.4s;
}
.active,
.accordion:hover {
background-color: #ccc;
}
.panel {
padding: 0 18px;
background-color: white;
display: none;
overflow: hidden;
}
.wrapper {
display: inline-block;
max-width: 1140px;
margin: 0 auto;
width: 100%;
text-align: center;
}
.stage_info,
.stage_img {
display: inline-block;
width: calc(50% - 80px);
vertical-align: top;
}
rect {
cursor: pointer;
z-index: 999;
position: relative;
}
rect:hover {
fill: #ccc;
pointer-events: all;
}
And my javascript:
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
I tried to do it as procedurally as possible as that seemed to be what you were going for in your JS.
I added value attributes to your stage buttons with the id of the corresponding rect elements, and I added a class called grey with the same properties as those applied when hovering.
let stgInf = document.querySelector(".stage_info");
let svg = document.querySelector("#stadium");
function onClick(num) {
let acc = stgInf.querySelector(`.accordion:nth-of-type(${num})`);
let panel = acc.nextElementSibling;
let rect = svg.querySelector(`rect#${acc.getAttribute("value")}`);
return () => {
acc.classList.toggle("active");
if (acc.classList.contains("active")) {
panel.style.display = "block";
rect.classList.add("grey");
} else {
panel.style.display = "none";
rect.classList.remove("grey");
}
}
}
function hover(num) {
let acc = stgInf.querySelector(`.accordion:nth-of-type(${num})`);
let rect = svg.querySelector(`rect#${acc.getAttribute("value")}`);
return (event) => {
if (event.type === "mouseenter") {
acc.classList.add("grey");
rect.classList.add("grey");
} else if (!acc.classList.contains("active")) {
acc.classList.remove("grey");
rect.classList.remove("grey");
}
}
}
let accs = stgInf.querySelectorAll(".accordion");
let i = 1;
for (let acc of accs) {
let rect = svg.querySelector(`rect#${acc.getAttribute("value")}`);
acc.addEventListener("click", onClick(i));
acc.addEventListener("mouseenter", hover(i));
acc.addEventListener("mouseout", hover(i));
rect.addEventListener("click", onClick(i));
rect.addEventListener("mouseenter", hover(i));
rect.addEventListener("mouseout", hover(i));
++i;
}
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
transition: 0.4s;
}
.panel {
padding: 0 18px;
background-color: white;
display: none;
overflow: hidden;
}
.wrapper {
display: inline-block;
max-width: 1140px;
margin: 0 auto;
width: 100%;
text-align: center;
}
.stage_info,
.stage_img {
display: inline-block;
width: calc(50% - 80px);
vertical-align: top;
}
rect {
cursor: pointer;
z-index: 999;
position: relative;
}
.grey,
.active,
.accordion:hover,
rect:hover {
fill: #ccc;
background-color: #ccc;
pointer-events: all;
}
<div class="wrapper">
<div class="stage_info">
<button class="accordion" value="stage1">Stage 1</button>
<div class="panel">
<p>Information here..</p>
</div>
<button class="accordion" value="stage2">Stage 2</button>
<div class="panel">
<p>Information here..</p>
</div>
<button class="accordion" value="stage3">Stage 3</button>
<div class="panel">
<p>Information here..</p>
</div>
<button class="accordion" value="stage4">Stage 4</button>
<div class="panel">
<p>Information here..</p>
</div>
</div>
<div class="stage_img">
<map id="big_stage">
<svg version="1.1" id="stadium" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="100%" height="100%" viewBox="0 0 456.122 451.02" enable-background="new 0 0 456.122 451.02"
xml:space="preserve">
<rect id="stage4" x="25.51" y="25.51" fill="#1C6131" width="200" height="200"/>
<rect id="stage3" x="230.612" y="25.51" fill="#1C6131" width="200" height="200"/>
<rect id="stage2" x="25.51" y="229.592" fill="#1C6131" width="200" height="200"/>
<rect id="stage1" x="230.612" y="229.592" fill="#1C6131" width="200" height="200"/>
</svg>
</map>
</div>
</div>
EDIT
I implemented the hover functionality you mentioned in your comment by adding mouseenter and mouseout event listeners in addition to the click listeners.
Related
I wanted to make a circle cursor and I copied the code from codepen
I am working in another IDE called Repl.it and so I copied the exact same code from codepen to repl.it (Note: I did use the correct code from codepen by compiling it first)
The code is not working in repl.it
I am not sure what I am missing, but I am pretty sure it has to do with the tags. Any help would be much appreciated.
My Output:
The cursor stays at the top left and does not move at all for some reason
This is the code:
const $bigBall = document.querySelector('.cursor__ball--big');
const $smallBall = document.querySelector('.cursor__ball--small');
const $hoverables = document.querySelectorAll('.hoverable');
// Listeners
document.body.addEventListener('mousemove', onMouseMove);
for (let i = 0; i < $hoverables.length; i++) {if (window.CP.shouldStopExecution(0)) break;
$hoverables[i].addEventListener('mouseenter', onMouseHover);
$hoverables[i].addEventListener('mouseleave', onMouseHoverOut);
}
// Move the cursor
window.CP.exitedLoop(0);function onMouseMove(e) {
TweenMax.to($bigBall, .4, {
x: e.pageX - 15,
y: e.pageY - 15 });
TweenMax.to($smallBall, .1, {
x: e.pageX - 5,
y: e.pageY - 7 });
}
// Hover an element
function onMouseHover() {
TweenMax.to($bigBall, .3, {
scale: 4 });
}
function onMouseHoverOut() {
TweenMax.to($bigBall, .3, {
scale: 1 });
}
body {
height: 100vh;
background: #010101;
cursor: none;
margin: 0;
display: flex;
font-family: monospace;
}
body h1,
body p,
body a {
color: #fff;
}
body a {
border-bottom: 2px solid #fff;
padding: 10px 0;
margin-top: 25px;
}
body .cursor {
pointer-events: none;
}
body .cursor__ball {
position: fixed;
top: 0;
left: 0;
mix-blend-mode: difference;
z-index: 1000;
}
body .cursor__ball circle {
fill: #f7f8fa;
}
body .left,
body .right {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
body .right {
background: #fff;
}
body .right a {
border-bottom: 2px solid #000;
}
body .right h1,
body .right p,
body .right a {
color: #000;
}
<div class="cursor">
<div class="cursor__ball cursor__ball--big ">
<svg height="30" width="30">
<circle cx="15" cy="15" r="12" stroke-width="0"></circle>
</svg>
</div>
<div class="cursor__ball cursor__ball--small">
<svg height="10" width="10">
<circle cx="5" cy="5" r="4" stroke-width="0"></circle>
</svg>
</div>
</div>
<div class="left">
<h1>Hello</h1>
<p>Check out this link:</p>
<a class="hoverable">Hover meh</a>
</div>
<div class="right">
<h1>Hello</h1>
<p>Check out this link:</p>
<a class="hoverable">Hover meh</a>
</div>
The code does not work here either, there is something that I am missing but not quite sure, could you please help?
Issue is with your html file.. I checkout Codepen and got compiled css and js code.
you also have to link js lib for this, as I told before, issue is in your html file.
below is the working code
enjoy !!
Mark as approved would be appreciated :)
body {
height: 100vh;
background: #010101;
cursor: none;
margin: 0;
display: flex;
font-family: monospace;
}
body h1, body p, body a {
color: #fff;
}
body a {
border-bottom: 2px solid #fff;
padding: 10px 0;
margin-top: 25px;
}
body .cursor {
pointer-events: none;
}
body .cursor__ball {
position: fixed;
top: 0;
left: 0;
mix-blend-mode: difference;
z-index: 1000;
}
body .cursor__ball circle {
fill: #f7f8fa;
}
body .left, body .right {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
body .right {
background: #fff;
}
body .right a {
border-bottom: 2px solid #000;
}
body .right h1, body .right p, body .right a {
color: #000;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Circle Cursor</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="cursor">
<div class="cursor__ball cursor__ball--big ">
<svg height="30" width="30">
<circle cx="15" cy="15" r="12" stroke-width="0"></circle>
</svg>
</div>
<div class="cursor__ball cursor__ball--small">
<svg height="10" width="10">
<circle cx="5" cy="5" r="4" stroke-width="0"></circle>
</svg>
</div>
</div>
<div class="left">
<h1>Hello</h1>
<p>Check out this link:</p>
<a class="hoverable">Hover meh</a>
</div>
<div class="right">
<h1>Hello</h1>
<p>Check out this link:</p>
<a class="hoverable">Hover meh</a>
</div>
</body>
<script>
const $bigBall = document.querySelector('.cursor__ball--big');
const $smallBall = document.querySelector('.cursor__ball--small');
const $hoverables = document.querySelectorAll('.hoverable');
// Listeners
document.body.addEventListener('mousemove', onMouseMove);
for (let i = 0; i < $hoverables.length; i++) {
$hoverables[i].addEventListener('mouseenter', onMouseHover);
$hoverables[i].addEventListener('mouseleave', onMouseHoverOut);
}
// Move the cursor
function onMouseMove(e) {
TweenMax.to($bigBall, .4, {
x: e.pageX - 15,
y: e.pageY - 15
})
TweenMax.to($smallBall, .1, {
x: e.pageX - 5,
y: e.pageY - 7
})
}
// Hover an element
function onMouseHover() {
TweenMax.to($bigBall, .3, {
scale: 4
})
}
function onMouseHoverOut() {
TweenMax.to($bigBall, .3, {
scale: 1
})
}
</script>
</html>
How do I replace the the class highlight with an id instead, so when I click outside of the products, it doesn't highlight that area?
I included the window.onload section with what I want to do, however I don't know how to change the class highlight into id. I can't think of an easier way than changing the class and then using the window.onload.
let overlay;
document.querySelectorAll('.product').forEach(function(path) {
path.onclick = chooseProduct;
})
function chooseProduct(e) {
if (overlay) overlay.classList.remove('highlight')
overlay = e.target
overlay.classList.add('highlight')
}
//What I want to add to the highlight class using id to remove black border when click outside of the products
// window.onload = function(){
// var hide = document.getElementById('?');
// document.onclick = function(e){
// if(e.target.id !== '?'){
// hide.style.display = 'none';
// }
// };
// };
var el = document.getElementsByClassName("color");
for (var i = 0; i < el.length; i++) {
el[i].onclick = changeColor;
}
function changeColor(e) {
let hex = e.target.getAttribute("data-hex");
if (overlay) overlay.style.fill = hex;
}
body,
html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
#container {
height: 200px;
width: 200px;
}
#product-svg {
position: relative;
z-index: 2;
background-size: 100%;
background-repeat: no-repeat;
background-position: 50%;
mix-blend-mode: multiply;
}
path {
fill: #CCCCCC;
}
#background-image {
position: absolute;
top: 0;
left: 0;
height: 200px;
width: 200px;
height: auto;
z-index: 1;
}
.colors {
display: flex;
position: fixed;
bottom: 2em;
right: 2em;
z-index: 3;
}
.color {
height: 36px;
width: 36px;
margin-left: 0.5em;
border-radius: 18px;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.3);
border: 2px solid #aaa;
cursor: pointer;
}
.highlight {
stroke-width: 10px;
stroke: #000;
}
<div id="container">
<svg id="product-svg" viewBox="0 0 744 1074">
<path class="product" d="M51 207.5L51 348L686 348L686 67L51 67L51 207.5Z" />
<path class="product" d="M51 544.5L51 685L686 685L686 404L51 404L51 544.5Z" />
<path class="product" d="M51 883.5L51 1024L686 1024L686 743L51 743L51 883.5Z" />
</svg>
<img id="background-image" src="boxes.jpg" alt="">
</div>
<div class="colors">
<div class="color" style="background-color: #ff0000" data-hex="#ff0000"></div>
<div class="color" style="background-color: #ffff33" data-hex="#ffff33"></div>
<div class="color" style="background-color: #3399ff" data-hex="#3399ff"></div>
</div>
your code is working as expected, except the part which you have mentioned in the question which highlight style of the selected product is not removed when you clicked outside the product.
In order to do that, simply I have added an Event Listener (removeHighlight()) by document.onclick = removeHighlight; to the whole document on click event. So whenever you click on anywhere in the DOM, that event listener will be triggered. What I'm do inside EventListener function is removing the class highlight from all products if and only if the click event was not triggered by clicking on either products or colours. Additionally I'm setting the overlay=null in order to remove the reference of the previously selected product, then clicking on colors won't fill the previously selected product with selected color if same conditions met and until you click again on a product.
let overlay;
document.querySelectorAll('.product').forEach(function(path) {
path.onclick = chooseProduct;
})
function chooseProduct(e) {
if (overlay) overlay.classList.remove('highlight')
overlay = e.target
overlay.classList.add('highlight')
}
var removeHighlight = function(e) {
var products = document.querySelectorAll('.product');
if(!e.target.classList.contains('product') && !e.target.classList.contains('color')){
overlay = null;
document.querySelectorAll('.product').forEach(function(prod){
prod.classList.remove('highlight');
});
}
}
document.onclick = removeHighlight;
var el = document.getElementsByClassName("color");
for (var i = 0; i < el.length; i++) {
el[i].onclick = changeColor;
}
function changeColor(e) {
let hex = e.target.getAttribute("data-hex");
if (overlay) overlay.style.fill = hex;
}
body,
html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
#container {
height: 200px;
width: 200px;
}
#product-svg {
position: relative;
z-index: 2;
background-size: 100%;
background-repeat: no-repeat;
background-position: 50%;
mix-blend-mode: multiply;
}
path {
fill: #CCCCCC;
}
#background-image {
position: absolute;
top: 0;
left: 0;
height: 200px;
width: 200px;
height: auto;
z-index: 1;
}
.colors {
display: flex;
position: fixed;
bottom: 2em;
right: 2em;
z-index: 3;
}
.color {
height: 36px;
width: 36px;
margin-left: 0.5em;
border-radius: 18px;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.3);
border: 2px solid #aaa;
cursor: pointer;
}
.highlight {
stroke-width: 10px;
stroke: #000;
}
<div id="container">
<svg id="product-svg" viewBox="0 0 744 1074">
<path class="product" d="M51 207.5L51 348L686 348L686 67L51 67L51 207.5Z" />
<path class="product" d="M51 544.5L51 685L686 685L686 404L51 404L51 544.5Z" />
<path class="product" d="M51 883.5L51 1024L686 1024L686 743L51 743L51 883.5Z" />
</svg>
<img id="background-image" src="boxes.jpg" alt="">
</div>
<div class="colors">
<div class="color" style="background-color: #ff0000" data-hex="#ff0000"></div>
<div class="color" style="background-color: #ffff33" data-hex="#ffff33"></div>
<div class="color" style="background-color: #3399ff" data-hex="#3399ff"></div>
</div>
jsfiddle
When a behavior is a result of a click event occurring anywhere but the tags meant to be clicked, it's most effective to register the document Object as the click event listener and control all clicks by Event Delegation.
register the document Object as the click event listener
document.onclick = selectPath;
the click event handler is selectPath(e)
collect all .product into a NodeList
const paths = document.querySelectorAll('.product');
if the user clicked any .product remove .highlight class from all .product and then add .highlight class to the .product user clicked
if (e.target.matches('.product')) {
paths.forEach(path => path.classList.remove('highlight'));
e.target.classList.add('highlight');
but if the user clicked any .color, then get it's [data-hex] value, and fill .highlight with the hex color if it exists (re: .highlight)
else if (e.target.matches('.color')) {
let hex = e.target.dataset.hex;
let selected = document.querySelector('.highlight');
if (selected) selected.style.fill = hex;
otherwise just remove the .highlight class if it exists.
paths.forEach(path => path.classList.remove('highlight'));
document.onclick = selectPath;
function selectPath(e) {
const paths = document.querySelectorAll('.product');
if (e.target.matches('.product')) {
paths.forEach(path => path.classList.remove('highlight'));
e.target.classList.add('highlight');
} else if (e.target.matches('.color')) {
let hex = e.target.dataset.hex;
let selected = document.querySelector('.highlight');
if (selected) selected.style.fill = hex;
} else {
paths.forEach(path => path.classList.remove('highlight'));
}
};
body,
html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
.container {
height: 200px;
width: 200px;
}
.svg {
position: relative;
z-index: 2;
background-size: 100%;
background-repeat: no-repeat;
background-position: 50%;
mix-blend-mode: multiply;
}
path {
fill: #CCCCCC;
}
.background {
position: absolute;
top: 0;
left: 0;
height: 200px;
width: 200px;
height: auto;
z-index: 1;
}
.circles {
position: fixed;
bottom: 2em;
right: 2em;
z-index: 3;
}
.color {
display: inline-block;
height: 36px;
width: 36px;
margin-left: 0.5em;
border-radius: 18px;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.3);
border: 2px solid #aaa;
cursor: pointer;
}
.highlight {
stroke-width: 10px;
stroke: #000;
}
<div class="container">
<svg class="svg" viewBox="0 0 744 1074">
<path class="product" d="M51 207.5L51 348L686 348L686 67L51 67L51 207.5Z" />
<path class="product" d="M51 544.5L51 685L686 685L686 404L51 404L51 544.5Z" />
<path class="product" d="M51 883.5L51 1024L686 1024L686 743L51 743L51 883.5Z" />
</svg>
<img class="background" src="boxes.jpg" alt="">
</div>
<div class="circles">
<div class="color" style="background-color: #ff0000" data-hex="#ff0000"></div>
<div class="color" style="background-color: #ffff33" data-hex="#ffff33"></div>
<div class="color" style="background-color: #3399ff" data-hex="#3399ff"></div>
</div>
You are setting "highlight" class only for products so you don't need id for what you are going to do.
you can just check if element which you clicked on has "product" class then first you remove all "highlight" classes and then add it to clicked product. If element doesn't have a "product" class then you just remove all "highlight" classes.
window.onload = function(){
document.onclick = function(e){
if(e.target.classList.contains("product")){
resetClass()
e.target.classList.add("highlight")
}else{
resetClass()
}
};
};
function resetClass(){
document.querySelectorAll(".highlight").forEach(item => {
item.classList.remove("highlight")
})
}
My code works just fine but for some reason when you click on the play button it takes a bit longer to switch over to the pause sign, and occasionally it takes a bit longer for the pause button to go to the play button. I also have one more question, when you click on the rain and beach icon there's a blue square border that I didn't remember putting, how do you remove it?
Thanks, Love2code
<!DOCTYPE html>
<html>
<head>
<title>Meditation App</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
<style>
*{
margin:0;
padding:0;
box-sizing:border-box;
}
.app{
height:100vh;
display:flex;
justify-content:space-evenly;
align-items:center;
}
.time-select,.sound-picker,.player-container{
height:80%;
flex:1;
display:flex;
flex-direction:column;
justify-content:space-evenly;
align-items:center;
}
.player-container{
position:relative;
}
.player-container svg{
position:absolute;
height:50%;
top:50%;
left:50%;
transform:translate(-50%,-50%);
pointer-events:none;
}
.time-display{
position:absolute;
bottom:10%;
color:white;
font-size:50px;
}
video{
position:fixed;
top:0%;
left:0%;
width:100%;
z-index:-10;
}
.time-select button,
.sound-picker button{
color:white;
width:30%;
height:10%;
background:none;
border:2px solid white;
cursor:pointer;
border-radius:5px;
font-size:20px;
transition:all 0.5s ease;
}
.time-select button:hover{
color:black;
background:white;
}
.sound-picker button{
border:none;
height:120px;
width:120px;
border-radius:50%;
}
.sound-picker button:nth-child(1){
background:#4972a1;
}
.sound-picker button:nth-child(2){
background:#a14f49;
}
.sound-picker:focus{
outline: none;
}
</style>
</head>
<body>
<div class="app">
<div class="vid-container">
<video Loop>
<source src="https://www.dropbox.com/s/wkdu9elom9o4r5g/rain%20%281%29.mp4?raw=1"/>
</video>
</div>
<div class="time-select">
<button data-time="120">2 Minutes</button>
<button data-time="300">5 Minutes</button>
<button data-time="600">10 Minutes</button>
</div>
<div class="player-container">
<audio class="song">
<source src="https://www.dropbox.com/s/jawlfpyyz83w2td/rain.mp3?raw=1"></source>
</audio>
<img src="https://www.dropbox.com/s/8unx3knosmefedk/download%20%281%29.svg?raw=1" class="play-container" alt="">
<svg class="track-outline"
width="453" height="453" viewBox="0 0 453 453" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="226.5" cy="226.5" r="216.5" stroke="white" stroke-width="20"/>
</svg>
<svg class="moving-outline"
width="453" height="453" viewBox="0 0 453 453" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="226.5" cy="226.5" r="216.5" stroke="#018EBA" stroke-width="20"/>
</svg>
<h3 class="time-display">0:00</h3>
</div>
<div class="sound-picker">
<button data-sound="https://www.dropbox.com/s/jawlfpyyz83w2td/rain.mp3?raw=1" data-video="https://www.dropbox.com/s/wkdu9elom9o4r5g/rain%20%281%29.mp4?raw=1"><img src="https://i.ibb.co/8BspYTV/rain-1.png"></button>
<button data-sound="https://www.dropbox.com/s/6k9nauf2ffyvfuu/beach.mp3?raw=1"
data-video="https://www.dropbox.com/s/tsdd86bxmax32jp/beach.mp4?raw=1"><img src="https://i.ibb.co/T0xw4k7/sun-umbrella.png"></button>
</div>
</body>
<script>
const app = () => {
const song = document.querySelector(".song");
const play = document.querySelector(".play-container");
const outline = document.querySelector(".moving-outline circle");
const video = document.querySelector(".vid-container video");
//Sounds
const sounds = document.querySelectorAll(".sound-picker button");
//Time Display
const timeDisplay = document.querySelector(".time-display");
//Get length of the outside
const outlineLength = outline.getTotalLength();
//Duration
let fakeDuration = 600;
outline.style.strokeDasharray = outlineLength;
outline.style.strokeDashoffset = outlineLength;
//play sounds
play.addEventListener("click", () => {
checkPlaying(song);
});
//stop and play the sounds
const checkPlaying = song =>{
if(song.paused){
song.play();
video.play();
play.src = 'https://www.dropbox.com/s/3zvnjkebwt1sjgq/download%20%283%29.svg?raw=1';
}else{
song.pause();
video.pause();
play.src = 'https://www.dropbox.com/s/8unx3knosmefedk/download%20%281%29.svg?raw=1';
}
}
};
app();
</script>
</html>
Because your SVGs are remotely sourced, it takes a bit of time to download them. I've created two hidden images with the remote sources. This will download these and have them ready in your cash for when you need them. I've also changed the sequence of when you switch the source path to come before you play the video.
I've set all elements to have an outline of none to take away the blue border when clicking on the image.
const app = () => {
const song = document.querySelector(".song");
const play = document.querySelector(".play-container");
const outline = document.querySelector(".moving-outline circle");
const video = document.querySelector(".vid-container video");
//Sounds
const sounds = document.querySelectorAll(".sound-picker button");
//Time Display
const timeDisplay = document.querySelector(".time-display");
//Get length of the outside
const outlineLength = outline.getTotalLength();
//Duration
let fakeDuration = 600;
outline.style.strokeDasharray = outlineLength;
outline.style.strokeDashoffset = outlineLength;
//play sounds
play.addEventListener("click", () => {
checkPlaying(song);
});
//stop and play the sounds
const checkPlaying = song => {
if (song.paused) {
play.src = 'https://www.dropbox.com/s/3zvnjkebwt1sjgq/download%20%283%29.svg?raw=1';
song.play();
video.play();
} else {
play.src = 'https://www.dropbox.com/s/8unx3knosmefedk/download%20%281%29.svg?raw=1';
song.pause();
video.pause();
}
}
};
app();
* {
margin: 0;
padding: 0;
box-sizing: border-box;
outline: none;
}
.app {
height: 100vh;
display: flex;
justify-content: space-evenly;
align-items: center;
}
.time-select,
.sound-picker,
.player-container {
height: 80%;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
}
.player-container {
position: relative;
}
.player-container svg {
position: absolute;
height: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
}
.time-display {
position: absolute;
bottom: 10%;
color: white;
font-size: 50px;
}
video {
position: fixed;
top: 0%;
left: 0%;
width: 100%;
z-index: -10;
}
.time-select button,
.sound-picker button {
color: white;
width: 30%;
height: 10%;
background: none;
border: 2px solid white;
cursor: pointer;
border-radius: 5px;
font-size: 20px;
transition: all 0.5s ease;
}
.time-select button:hover {
color: black;
background: white;
}
.sound-picker button {
border: none;
height: 120px;
width: 120px;
border-radius: 50%;
}
.sound-picker button:nth-child(1) {
background: #4972a1;
}
.sound-picker button:nth-child(2) {
background: #a14f49;
}
.sound-picker:focus {
outline: none;
}
<img src="https://www.dropbox.com/s/3zvnjkebwt1sjgq/download%20%283%29.svg?raw=1" style="display:none;">
<img src="https://www.dropbox.com/s/8unx3knosmefedk/download%20%281%29.svg?raw=1" style="display:none;">
<div class="app">
<div class="vid-container">
<video Loop>
<source src="https://www.dropbox.com/s/wkdu9elom9o4r5g/rain%20%281%29.mp4?raw=1"/>
</video>
</div>
<div class="time-select">
<button data-time="120">2 Minutes</button>
<button data-time="300">5 Minutes</button>
<button data-time="600">10 Minutes</button>
</div>
<div class="player-container">
<audio class="song">
<source src="https://www.dropbox.com/s/jawlfpyyz83w2td/rain.mp3?raw=1"></source>
</audio>
<img src="https://www.dropbox.com/s/8unx3knosmefedk/download%20%281%29.svg?raw=1" class="play-container" alt="">
<svg class="track-outline" width="453" height="453" viewBox="0 0 453 453" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="226.5" cy="226.5" r="216.5" stroke="white" stroke-width="20"/>
</svg>
<svg class="moving-outline" width="453" height="453" viewBox="0 0 453 453" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="226.5" cy="226.5" r="216.5" stroke="#018EBA" stroke-width="20"/>
</svg>
<h3 class="time-display">0:00</h3>
</div>
<div class="sound-picker">
<button data-sound="https://www.dropbox.com/s/jawlfpyyz83w2td/rain.mp3?raw=1" data-video="https://www.dropbox.com/s/wkdu9elom9o4r5g/rain%20%281%29.mp4?raw=1"><img src="https://i.ibb.co/8BspYTV/rain-1.png"></button>
<button data-sound="https://www.dropbox.com/s/6k9nauf2ffyvfuu/beach.mp3?raw=1" data-video="https://www.dropbox.com/s/tsdd86bxmax32jp/beach.mp4?raw=1"><img src="https://i.ibb.co/T0xw4k7/sun-umbrella.png"></button>
</div>
My problem is that i wanted to make a fixed menubar on top of the page when scrolled, that wasn't so hard, but the hard part for me is that, when i link it to a certain part from the menubar from external html the menubar shows up and it is fixed on the top of the page and it works perfectly when i scroll down, but when i scroll up, it stays there
<!DOCTYPE html>
<html>
<head>
<title>SMINT Demo</title>
<meta name = "keywords" content = "" />
<meta name = "description" content = "" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, minimum-scale=1 user-scalable=no">
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400,700' rel='stylesheet' type='text/css'>
<link href="css/demo.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.smint.js"></script>
<script type="text/javascript">
$(document).ready( function() {
$('.subMenu').smint({
'scrollSpeed' : 1000
});
});
(function(){
$.fn.smint = function( options ) {
// adding a class to users div
$(this).addClass('smint');
var settings = $.extend({
'scrollSpeed ' : 500
}, options);
return $('.smint a').each( function() {
if ( settings.scrollSpeed ) {
var scrollSpeed = settings.scrollSpeed;
}
///////////////////////////////////
// get initial top offset for the menu
var stickyTop = $('.smint').offset().top;
// check position and make sticky if needed
var stickyMenu = function(){
// current distance top
var scrollTop = $(window).scrollTop();
// if we scroll more than the navigation, change its position to fixed and add class 'fxd', otherwise change it back to absolute and remove the class
if (scrollTop > stickyTop) {
$('.smint').css({ 'position': 'fixed', 'top':0 }).addClass('fxd');
} else {
$('.smint').css({ 'position': 'absolute', 'top':stickyTop }).removeClass('fxd');
}
};
// run function
stickyMenu();
// run function every time you scroll
$(window).scroll(function() {
stickyMenu();
});
///////////////////////////////////////
$(this).on('click', function(e){
// gets the height of the users div. This is used for off-setting the scroll so th emenu doesnt overlap any content in the div they jst scrolled to
var selectorHeight = $('.smint').height();
// stops empty hrefs making the page jump when clicked
e.preventDefault();
// get id pf the button you just clicked
var id = $(this).attr('id');
// gets the distance from top of the div class that matches your button id minus the height of the nav menu. This means the nav wont initially overlap the content.
var goTo = $('div.'+ id).offset().top -selectorHeight;
// Scroll the page to the desired position!
$("html, body").animate({ scrollTop: goTo }, scrollSpeed);
});
});
};
})();
function showImage(imgName) {
document.getElementById('largeImg').src = imgName;
showLargeImagePanel();
unselectAll();
}
function showLargeImagePanel() {
document.getElementById('largeImgPanel').style.visibility = 'visible';
}
function unselectAll() {
if(document.selection) document.selection.empty();
if(window.getSelection) window.getSelection().removeAllRanges();
}
function hideMe(obj) {
obj.style.visibility = 'hidden';
}
</script>
<style>
* {margin: 0; padding: 0; outline: 0;}
body {
color: #f8e0b3;
font-size: 12px;
background:#f8e0b3;
}
h1, h2 {
font-family: 'Open Sans', sans-serif;
font-weight: 300;
margin:0 0 15px 0;
}
h1 {
font-size: 36px;
letter-spacing: -2px;
line-height: 100%;
}
h1.title {
font-size: 46px;
font-weight: 700;
color: #f8e0b3;
}
h2 {
font-size: 24px;
}
p {
margin: 0 0 15px 0;
}
.menuBtn {
background: center center no-repeat transparent;
background: #f8e0b3;
display: block;
width: 40px;
height: 40px;
position: absolute;
top: 0;
left: 10px;
}
.clear {
clear: both;
}
.wrap {
/*background:url(../images/bg.png) top left repeat-x;*/
width: 100%;
max-width: 1140px;
min-width: 960px;
z-index: 10;
position: relative;
margin: 0 auto;
padding: 0;
}
.section {
width: 100%;
max-width: 1140px;
min-width: 960px;
z-index: 10;
position: relative;
margin: 0 auto;
padding: 0 0 20px 0;
}
.inner {
width: 960px;
margin: 0 auto;
position: relative;
min-height: 50px;
padding:30px 0;
font-size: 18px;
font-family: 'Open Sans', sans-serif;
font-weight: 300;
padding:30px 0;
}
/* This is the selector i used for my menu, it needs to be set as position:absolute; */
.subMenu {
position: absolute;
top: 400px;
height: 50px;
z-index: 1000;
width: 100%;
max-width: 1140px;
min-width: 960px;
background: #ff0000; /*за главна категория */
}
.subMenu .inner {
padding:0;
font-weight: 400;
}
.subNavBtn {
display: block;
height: 35px;
width: 8%;
float: left;
margin: 0px 0px 0 0;
text-decoration: none;
font-size: 14px;
padding: 15px 2% 0 2%;
text-align: center;
color: #fff;
}
.end {
margin: 0;
}
/* SECTIONS */
.sTop {
min-height: 630px;
background:#f8e0b3;
color:#3d3d3d;
}
.s1 {
min-height: 500px;
background: #f8e0b3;
}
.s2 {
min-height: 500px;
background: #f8e0b3;
}
.s3 {
min-height: 500px;
background: #f8e0b3;
}
.s4 {
min-height: 500px;
background: #f8e0b3;
}
.s5 {
min-height: 500px;
background: #f8e0b3;
}
.s6 {
min-height: 500px;
background: #f8e0b3;
}
.s7 {
min-height: 500px;
background: #f8e0b3;
}
h1.border {
border-style: solid;
border-width: 10px;
border-color: #ff0000;
}
h1 {
text-align: center;
}
p.border {
border-style: solid;
border-width: 10px;
border-color: #ff0000;
}
p {
text-align: center;
}
#largeImgPanel {
text-align: center;
visibility: hidden;
position: fixed;
z-index: 100;
top: 0; left: 0; width: 100%; height: 100%;
background-color: rgba(100,100,100, 0.5);
}
#displayImage{
border-style: solid;
border-color: red;
}
</style>
</head>
<body>
<div class="wrap">
<div class="subMenu" >
<div class="inner">
Блузи
Ризи
Сака
Аксесоари
Якета
Панталони/Дънки
Обувки
Спортни стоки
</div>
</div>
<div class="section sTop">
<div class="inner"><img src="heading.jpg" alt="заглавие">
<h1 class="border">Област Пловдив</h1>
<p class="border">Мъжки блузи</p>
</div>
<br class="clear">
</div>
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/bluzi s kus dulag rukav/2.jpg" width="200" height="200" name="show">
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/bluzi s kus dulag rukav/3.jpg" width="200" height="200" name="show">
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/bluzi s kus dulag rukav/4.jpg" width="200" height="200" name="show">
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/bluzi s kus dulag rukav/5.jpg" width="200" height="200" name="show">
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/bluzi s kus dulag rukav/6.jpg" width="200" height="200" name="show">
<div class="section s1">
<h1 class="border"><font color="black"><a name="mujkirizi">Ризи</a><font></h1>
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/rizi/hm (1).jpg" width="200" height="200" name="show">
</div>
<div class="section s2">
<h1 class="border"><font color="black"><a name="mujkisaka">Сака</a><font></h1>
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/rizi/hm (1).jpg" width="200" height="200" name="show">
</div>
<div class="section s3">
<h1 class="border"><font color="black"><a name="mujkiaksesoari"> Аксесоари</a><font></h1>
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/rizi/hm (1).jpg" width="200" height="200" name="show">
</div>
<div class="section s4">
<h1 class="border"><font color="black"><a name="mujkiiaketa"> Якета</a><font></h1>
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/rizi/hm (1).jpg" width="200" height="200" name="show">
</div>
<div class="section s5">
<h1 class="border"><font color="black"><a name="mujkipantaloni"> Панталони/Дънки</a><font></h1>
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/rizi/hm (1).jpg" width="200" height="200" name="show">
</div>
<div class="section s6">
<h1 class="border"><font color="black"><a name="mujkiobuvki"> Обувки</a><font></h1>
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/rizi/hm (1).jpg" width="200" height="200" name="show">
</div>
<div class="section s7">
<h1 class="border"><font color="black"><a name="mujkisportnistoki"> Спортни стоки</a><font></h1>
<img id="displayImage" style="cursor:pointer" onclick="showImage(this.src)" src="hm/mujko/rizi/hm (1).jpg" width="200" height="200" name="show">
</div>
<div id="largeImgPanel" onclick="hideMe(this);">
<img id="largeImg" style="height: 100%; margin: 0; padding: 0;" />
</div>
</body>
</html>
It works for me, it's fixed when i scroll down, and when i come back on the top of the page it goes where it was at the beginning, i don't get your problem, can you be more specific?
Well, to be more specific, i have the menubar that is fixed when i scroll down or up and it work perfectly when i open this specific html. This menubar contain 7 submenus and my idea is that when i use an external html with link to for example submenu 3 using (it opens this specific html and scroll down to submenu 3)but the menubar doesnt move when i scroll up , it only works(stay fixed at the top)when i scroll down
I have an SVG “map”, and I want to implement a simple tooltip when the mouse is hovered over a rectangle.
For the tooltip I want to use this plugin.
Here is how I link SVG to HTML:
<object data="map.svg" type="image/svg+xml" id="map" width="1840" height="940"></object>
The First Try was like this:
var svgobject = document.getElementById('map');
if ('contentDocument' in svgobject) {
var svgdom = $(svgobject.contentDocument);
$("#rect4578").tooltip.pop(this, '#ToltipContent');
}
And the tooltip container is as follows:
<div style="display:none;">
<div id="ToltipContent">
<h2>Header</h2>
<img src="img/img.jpg" style="float:right;" />
Some text
</div>
</div>
I also added the toolpip class to the rect4578 as it is explained on the plugin site. However it didn't work.
Then I tried to add the plugin invocation inside onmouseover attribute of the SVG rectangle.
onmouseover="tooltip.pop('#rect4578', '#ToltipContent')"
And also I got nothing.
However, if I change the opacity of the rectangle by using either of above described methods it works.
And the question is what is the right way to use this plugin to implement tooltip for the SVG?
Thank you.
Since I didn't have access to your object, I used an svg from w3schools and it seemed to work fine. Here's what I did to get it to work:
.hide {display:none;}
#object {width: 100px; overflow: hidden; margin: 0 auto;}
#object svg {padding: 20px;}
div#mcTooltip h2 {
margin-top: 10px;
line-height: 1;
}
#mcTooltip ul, #mcTooltip ol {
padding-left: 20px;
}
div#mcTooltip {
line-height: 16px;
border-width: 1px;
color: #333;
border-color: #bbb;
padding: 20px;
font-size: 12px;
font-family: Verdana, Arial;
border-radius: 6px;
box-shadow: 0 1px 4px #aaa;
}
div#mcTooltip, div.mcTooltipInner {
background-color: #eee;
}
div#mcTooltip a {
color: #069;
}
div#mcTooltip a:hover {
color: #333;
}
div#mcTooltipWrapper {
position: absolute;
visibility: hidden;
overflow: visible;
z-index: 9999999999;
top: 0;
}
div#mcTooltip {
float: left;
border-style: solid;
position: relative;
overflow: hidden;
}
div.mcTooltipInner {
float: left;
position: relative;
width: auto;
height: auto;
}
div#mcTooltip, div#mcTooltip div {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
div#mcttCo {
position: absolute;
text-align: left;
}
div#mcttCo em, div#mcttCo b {
display: block;
width: 0;
height: 0;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="http://www.menucool.com/Content/widgets?v=pWIjgyLaRd3JgPu8kRMWTBEFhPIETaPsvP81TXLgnbE1"></script>
<div class="hide">
<div id="toolTipContent">Tooltip text goes here</div>
</div>
<br/>
<br/>
<br/>
<object id="object" type="image/svg+xml" data="http://www.schepers.cc/svg/blendups/smiley.svg"><svg width="100" height="100">
<rect width="100" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" onmouseover="tooltip.pop(this, '#toolTipContent', {position:2})" />
</svg><svg width="100" height="100">
<rect width="100" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" onmouseover="tooltip.pop(this, '#toolTipContent', {position:2})" />
</svg><svg width="100" height="100">
<rect width="100" height="100" style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)" onmouseover="tooltip.pop(this, '#toolTipContent', {position:2})" />
</svg></object>
It looks like the problem with your original approach is that the object tag does not support 'onmouseover' https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object. I am using the an img tag instead. This is a very minor change from the first answer.
var svg = document.getElementById('kiwi');
svg.onmouseover = function() {tooltip.pop(this, '#tooltip');}
.hide {display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="http://www.menucool.com/Content/widgets?v=pWIjgyLaRd3JgPu8kRMWTBEFhPIETaPsvP81TXLgnbE1"></script>
<div class="">
<img id="kiwi" height="200" width="200" src="http://s.cdpn.io/3/kiwi.svg">
</div>
<div class="hide">
<span id="tooltip" >
This is a tooltip.
</span>
</div>