I am trying to make iframes resizable the same way that a frameset with frames are. This is what I am trying to reproduce:
<!DOCTYPE html>
<html>
<frameset rows="80%,20%">
<frame src="https://www.w3schools.com" />
<frame src="https://www.tutorialspoint.com/html/top_frame.htm" />
</frameset>
</html>
See: Online Html Editor
I don't want to use JavaScript because it's widely claimed the iframe has the same functionality as frames and framesets, see: Obsolete Eements - W3. Its simply bad practice to use JavaScript for something that can be achieved perfectly without.
Using the resize property, is no good because it produces an icon in the bottom right hand corner the same as textarea. See: Resizable Columns without JQuery.
I decided to give up trying to do it without JavaScript. I managed to get it to work smoothly by making sure it gets the position of the mouse cursor correctly, even when hovering over the iframe. It requires access to the domain in the iframe to use postMessage to get the mouse coordinates but no problem, I am only going to use this to create debug tools on my own website anyway. It can be resized in all directions by dragging an edge or corner.
<!DOCTYPE html>
<style>
iframe {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 100%;
height: 100%;
border: none;
}
.frame_holder {
display: block;
top: 300px;
left: 200px;
height: 500px;
width: 350px;
position: absolute;
}
.resizer {
position: absolute;
width: 7px;
height: 7px;
z-index: 2;
}
.resizer.n {
top: -7px;
left: 0px;
width: 100%;
cursor: n-resize;
}
.resizer.s {
bottom: -7px;
left: 0px;
width: 100%;
cursor: s-resize;
}
.resizer.w {
top: 0px;
left: -7px;
height:100%;
cursor: w-resize;
}
.resizer.e {
top: 0px;
right: -7px;
height:100%;
cursor: e-resize;
}
.resizer.nw {
top: -7px;
left: -7px;
cursor: nw-resize;
}
.resizer.ne {
top: -7px;
right: -7px;
cursor: ne-resize;
}
.resizer.sw {
bottom: -7px;
left: -7px;
cursor: sw-resize;
}
.resizer.se {
bottom: -7px;
right: -7px;
cursor: se-resize;
}
</style>
<body>
<div class="frame_holder">
<div class="resizer n"></div>
<div class="resizer s"></div>
<div class="resizer w"></div>
<div class="resizer e"></div>
<div class="resizer ne"></div>
<div class="resizer nw"></div>
<div class="resizer sw"></div>
<div class="resizer se"></div>
<iframe class="frame" src="https://stackoverflow.com/questions/74724195/how-can-i-make-an-iframe-resizeable-without-javascript"></iframe>
</div>
</body>
<script>
$ = typeof $ == "undefined" ? [] : $;
$[window.location.pathname]=function()
{
window.addEventListener('contextmenu', (e) => {e.preventDefault()});
const el = document.querySelector(".frame_holder");
const iframe = document.querySelector(".frame");
const resizers = document.querySelectorAll(".resizer");
var currentResizer = 0;
var prevX;
var prevY;
function resize(el, size)
{
Object.keys(size).forEach((i) =>
{
el.style[i] = size[i] + "px";
});
}
window.onmessage = function(e)
{
try
{
var msg = JSON.parse(e.data);
}
catch (e)
{
return;
}
if (msg.type == "mouseUp")
{
el.isResizing=false;
//window.removeEventListener("mousemove", mousemove);
//window.removeEventListener("mouseup", mouseup);
return
}
if (!el.isResizing)
{
try
{
window.removeEventListener("mousemove", mousemove);
//window.removeEventListener("mouseup", mouseup);
}
catch (e)
{ }
return;
}
const rect = el.getBoundingClientRect();
let mouseX = msg.mouseX + rect.left;
let mouseY = msg.mouseY + rect.top;
//let top = Math.min(rect.top - (prevY - mouseY), 0);
//let left = Math.min(rect.left - (prevX - mouseX), 0);
let top = rect.top - (prevY - mouseY);
let left = rect.left - (prevX - mouseX);
let width = rect.width + (prevX - mouseX);
let width1 = rect.width - (prevX - mouseX);
let height= rect.height - (prevY - mouseY);
let height1 = rect.height + (prevY - mouseY);
//let vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
//let vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)
let currentResizer = this.currentResizer;
if (currentResizer.classList.contains("n"))
resize(el, {top: top, height: height1});
else if (currentResizer.classList.contains("w"))
resize(el, {left: left, width: width});
else if (currentResizer.classList.contains("s"))
resize(el, {height: height});
else if (currentResizer.classList.contains("e"))
resize(el, {width: width1});
else if (currentResizer.classList.contains("sw"))
resize(el, {left: left, width: width, height: height});
else if (currentResizer.classList.contains("ne"))
resize(el, {top: top, width: width1, height: height1});
else if (currentResizer.classList.contains("nw"))
resize(el, {top: top, left: left, width: width, height: height1});
else if (currentResizer.classList.contains("se"))
resize(el, {width: width1, height: height});
else
resize(el, {left: left, top: top});
prevX = mouseX;
prevY = mouseY;
};
for (let resizer of resizers)
{
if (resizer.classList.contains("n"))
iframe.style.borderTop = "groove 2px";
else if (resizer.classList.contains("s"))
iframe.style.borderBottom = "groove 2px";
else if (resizer.classList.contains("w"))
iframe.style.borderLeft = "groove 2px";
else if (resizer.classList.contains("e"))
iframe.style.borderRight = "groove 2px";
resizer.addEventListener("mousedown", mousedown);
function mousedown(e)
{
currentResizer = e.target;
//window.currentResizer = e.target;
window.currentResizer = currentResizer;
el.isResizing = true;
prevX = e.clientX;
prevY = e.clientY;
window.addEventListener("mousemove", mousemove);
window.addEventListener("mouseup", mouseup);
//msg.mouseX=344, msg.mouseY=830
//e.clientX=551, e.clientY=800
function mousemove(e)
{
if (!el.isResizing)
{
window.removeEventListener("mousemove", mousemove);
window.removeEventListener("mouseup", mouseup);
return;
}
const rect = el.getBoundingClientRect();
//let top = Math.min(rect.top - (prevY - e.clientY), 0);
//let left = Math.min(rect.left - (prevX - e.clientX), 0);
let top = rect.top - (prevY - e.clientY);
let left = rect.left - (prevX - e.clientX);
let width = rect.width + (prevX - e.clientX);
let width1 = rect.width - (prevX - e.clientX);
let height= rect.height - (prevY - e.clientY);
let height1 = rect.height + (prevY - e.clientY);
if (currentResizer.classList.contains("n"))
resize(el, {top: top, height: height1});
else if (currentResizer.classList.contains("w"))
resize(el, {left: left, width: width});
else if (currentResizer.classList.contains("s"))
resize(el, {height: height});
else if (currentResizer.classList.contains("e"))
resize(el, {width: width1});
else if (currentResizer.classList.contains("sw"))
resize(el, {left: left, width: width, height: height});
else if (currentResizer.classList.contains("ne"))
resize(el, {top: top, width: width1, height: height1});
else if (currentResizer.classList.contains("nw"))
resize(el, {top: top, left: left, width: width, height: height1});
else if (currentResizer.classList.contains("se"))
resize(el, {width: width1, height: height});
else
resize(el, {left: left, top: top});
prevX = e.clientX;
prevY = e.clientY;
}
function mouseup()
{
el.isResizing = false;
console.log("mouseup");
window.removeEventListener("mousemove", mousemove);
//window.removeEventListener("mouseup", mouseup);
}
}
}
}
if (document.readyState!='loading') $[window.location.pathname](); else document.addEventListener('DOMContentLoaded', $[window.location.pathname]);
</script>
This code goes inside the iframe:
if (!window.isTop)
{
function mouseup(e)
{
window.top.postMessage(JSON.stringify({ type: "mouseUp" }), '*');
}
function mousemove(e)
{
window.top.postMessage(JSON.stringify({ type: "mouseMove", mouseX: e.clientX, mouseY: e.clientY }), '*');
}
window.addEventListener("mouseup", mouseup);
window.addEventListener("mousemove", mousemove);
}
In html canvas, what I want to achieve is a white noise effect on a picture. So I get the picture, get its ImageData, modify it's alpha and draw it back.
var bat = new Image();
bat.src = "data:image/png;base64,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"
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = 250;
canvas.height = 250;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(bat, 0, 0);
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
if (data[i] != 0 || data[i + 1] != 0 || data[i + 2] != 0) {
data[i + 3] = Math.floor(Math.random() * 255);
}
}
ctx.putImageData(imageData, 0, 0);
requestAnimationFrame(animate);
}
animate();
<!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>Bat</title>
<link rel="stylesheet" href="style.css" />
<style>
#main {
display: flex;
flex-direction: row;
}
#canvas {
border: 1px solid black;
width: 150px;
height: 150px;
}
</style>
</head>
<body>
<div id="main">
<canvas id="canvas"></canvas>
<br />
</div>
<script src="script.js"></script>
</body>
</html>
The result is what I need. But the issue is that when you use putImageData, even if the alpha is 0, it won't be transparent.
So I use a temporary canvas, draw the picture on it, modify it and then draw it back on the canvas.
var bat = new Image();
bat.src = "data:image/png;base64,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";
var canvas2 = document.getElementById('canvas2');
var ctx2 = canvas2.getContext('2d');
var tempCanvas = document.createElement('canvas');
var tempContext = tempCanvas.getContext('2d');
canvas2.width = 250;
canvas2.height = 250;
tempCanvas.width = 250;
tempCanvas.height = 250;
var img = new Image();
var alpha = 0;
function animate2() {
alpha += 0.1;
ctx2.clearRect(0, 0, canvas.width, canvas.height);
ctx2.fillStyle = 'blue';
ctx2.fillRect(0, 0, 250, 250);
tempContext.drawImage(bat, 0, 0);
var imageData = tempContext.getImageData(
0,
0,
tempCanvas.width,
tempCanvas.height
);
var data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
if (data[i] != 0 || data[i + 1] != 0 || data[i + 2] != 0) {
//data[i + 3] = Math.floor(Math.random() * 255);
data[i + 3] = 123;
//data[i + 3] = alpha;
}
}
tempContext.putImageData(imageData, 0, 0);
img.src = tempCanvas.toDataURL('image/png');
ctx2.drawImage(img, 0, 0);
requestAnimationFrame(animate2);
}
animate2();
<!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>Bat</title>
<link rel="stylesheet" href="style.css" />
<style>
#main {
display: flex;
flex-direction: row;
}
#canvas2 {
border: 1px solid black;
width: 150px;
height: 150px;
}
</style>
</head>
<body>
<div id="main">
<canvas id="canvas"></canvas>
<br />
<canvas id="canvas2"></canvas>
</div>
<script src="script.js"></script>
</body>
</html>
But whenever I want to change the alpha randomly with:
data[i + 3] = Math.floor(Math.random() * 255);
The picture won't display. And if I want to update the alpha other time with:
var alpha = 0;
alpha += 0.1
data[i + 3] = alpha;
The picture flickers...
What is the correct way to get my "white noise" picture that would be transparent so I can see the background through it?
Here is a link of a stackblitz with the demo in it.
First, don't call getImageData every frame. All you need is to know where the black pixels are in the image, these won't change so you can keep the same ImageData object all along, avoid slow read-backs from the GPU.
Then, you can drawImage() a canvas directly. No need to go through a new Image with a toDataURL() which will load your image async and indeed make your animation flicker.
So this would give:
var bat = new Image();
bat.src = "data:image/png;base64,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";
var canvas2 = document.getElementById('canvas2');
var ctx2 = canvas2.getContext('2d');
var tempCanvas = document.createElement('canvas');
var tempContext = tempCanvas.getContext('2d');
canvas2.width = 250;
canvas2.height = 250;
tempCanvas.width = 250;
tempCanvas.height = 250;
// store the ImageData in a way it's accessible at every frame
var imageData;
bat.onload = (evt) => { // always wait for the assets to load
ctx2.drawImage(bat, 0, 0);
imageData = ctx2.getImageData(0, 0, 250, 250);
animate2();
}
var alpha = 0;
function animate2() {
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
ctx2.fillStyle = 'blue';
ctx2.fillRect(0, 0, 250, 250);
var data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
if (data[i] != 0 || data[i + 1] != 0 || data[i + 2] != 0) {
data[i + 3] = Math.floor(Math.random() * 255);
}
}
tempContext.putImageData(imageData, 0, 0);
// drawImage the tempCanvas directly
ctx2.drawImage(tempCanvas, 0, 0);
requestAnimationFrame(animate2);
}
#main {
display: flex;
flex-direction: row;
}
#canvas2 {
border: 1px solid black;
width: 150px;
height: 150px;
}
<div id="main">
<canvas id="canvas2"></canvas>
</div>
But you don't even need a second canvas here, you can draw "behind" the current drawing on a canvas thanks to the "destination-over" compositing mode. You can even use more compositing operations to clip that background so that only the image is "colored":
var bat = new Image();
bat.src = "data:image/png;base64,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";
var canvas2 = document.getElementById('canvas2');
var ctx2 = canvas2.getContext('2d');
canvas2.width = 250;
canvas2.height = 250;
// store the ImageData in a way it's accessible at every frame
var imageData;
bat.onload = (evt) => { // always wait for the assets to load
ctx2.drawImage(bat, 0, 0);
imageData = ctx2.getImageData(0, 0, 250, 250);
animate2();
}
function animate2() {
var data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
if (data[i] != 0 || data[i + 1] != 0 || data[i + 2] != 0) {
data[i + 3] = Math.floor(Math.random() * 255);
}
}
ctx2.putImageData(imageData, 0, 0);
ctx2.globalCompositeOperation = "destination-over"; // draw behind
ctx2.fillStyle = 'blue';
ctx2.fillRect(0, 0, 250, 250);
ctx2.globalCompositeOperation = "destination-in"; // keep only where new pixels are opaque
ctx2.drawImage(bat, 0, 0);
ctx2.globalCompositeOperation = "source-over"; // default
requestAnimationFrame(animate2);
}
#main {
display: flex;
flex-direction: row;
}
#canvas2 {
border: 1px solid black;
width: 150px;
height: 150px;
background: yellow
}
<div id="main">
<canvas id="canvas2"></canvas>
</div>
EDIT 1: Quick codepen of my current issue: https://codepen.io/zuffdaddy/pen/QWGewKr
See how the clip path is massive while the image is small? How do align those two?
Original:
Intro:
I'm making an Attack Disc for a submarine simulator game.
The disc has multiple circular rings that all rotate and so far I have that part complete, but there's some overlapping transparent plastic parts that sit on top the rings and rotate as well.
Problem:
The problem is the plastic pieces that rotate on top are complex shapes (image of the shape here). The user needs to be able to click around them to manipulate the rings beneath them but also be able to click on them to rotate them as well.
SVG Clipping paths seem to be the way to go but I cannot get the svg clip path to align with the image.
Please ignore the JS, it's a temporary rotating script I pulled from another question here and will be rewritten towards finalization.
///////////////////////////////
// ------- rotate -------- //
///////////////////////////////
(function() {
var init, rotate, start, stop,
active = false,
angle = 0,
rotation = 0,
startAngle = 0,
center = {
x: 0,
y: 0
},
R2D = 180 / Math.PI,
rot = document.getElementById('attack_disc');
init = function() {
rot.addEventListener("mousedown", start, false);
$(document).bind('mousemove', function(event) {
if (active === true) {
event.preventDefault();
rotate(event);
}
});
$(document).bind('mouseup', function(event) {
event.preventDefault();
stop(event);
});
};
start = function(e) {
e.preventDefault();
var bb = this.getBoundingClientRect(),
t = bb.top,
l = bb.left,
h = bb.height,
w = bb.width,
x, y;
center = {
x: l + (w / 2),
y: t + (h / 2)
};
x = e.clientX - center.x;
y = e.clientY - center.y;
startAngle = R2D * Math.atan2(y, x);
return active = true;
};
rotate = function(e) {
e.preventDefault();
var x = e.clientX - center.x,
y = e.clientY - center.y,
d = R2D * Math.atan2(y, x);
rotation = d - startAngle;
return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
};
stop = function() {
angle += rotation;
return active = false;
};
init();
}).call(this);
(function() {
var init, rotate, start, stop,
active = false,
angle = 0,
rotation = 0,
startAngle = 0,
center = {
x: 0,
y: 0
},
R2D = 180 / Math.PI,
rot = document.getElementById('course_disc');
init = function() {
rot.addEventListener("mousedown", start, false);
$(document).bind('mousemove', function(event) {
if (active === true) {
event.preventDefault();
rotate(event);
}
});
$(document).bind('mouseup', function(event) {
event.preventDefault();
stop(event);
});
};
start = function(e) {
e.preventDefault();
var bb = this.getBoundingClientRect(),
t = bb.top,
l = bb.left,
h = bb.height,
w = bb.width,
x, y;
center = {
x: l + (w / 2),
y: t + (h / 2)
};
x = e.clientX - center.x;
y = e.clientY - center.y;
startAngle = R2D * Math.atan2(y, x);
return active = true;
};
rotate = function(e) {
e.preventDefault();
var x = e.clientX - center.x,
y = e.clientY - center.y,
d = R2D * Math.atan2(y, x);
rotation = d - startAngle;
return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
};
stop = function() {
angle += rotation;
return active = false;
};
init();
}).call(this);
(function() {
var init, rotate, start, stop,
active = false,
angle = 0,
rotation = 0,
startAngle = 0,
center = {
x: 0,
y: 0
},
R2D = 180 / Math.PI,
rot = document.getElementById('aob_disc');
init = function() {
rot.addEventListener("mousedown", start, false);
$(document).bind('mousemove', function(event) {
if (active === true) {
event.preventDefault();
rotate(event);
}
});
$(document).bind('mouseup', function(event) {
event.preventDefault();
stop(event);
});
};
start = function(e) {
e.preventDefault();
var bb = this.getBoundingClientRect(),
t = bb.top,
l = bb.left,
h = bb.height,
w = bb.width,
x, y;
center = {
x: l + (w / 2),
y: t + (h / 2)
};
x = e.clientX - center.x;
y = e.clientY - center.y;
startAngle = R2D * Math.atan2(y, x);
return active = true;
};
rotate = function(e) {
e.preventDefault();
var x = e.clientX - center.x,
y = e.clientY - center.y,
d = R2D * Math.atan2(y, x);
rotation = d - startAngle;
return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
};
stop = function() {
angle += rotation;
return active = false;
};
init();
}).call(this);
(function() {
var init, rotate, start, stop,
active = false,
angle = 0,
rotation = 0,
startAngle = 0,
center = {
x: 0,
y: 0
},
R2D = 180 / Math.PI,
rot = document.getElementById('bearing_lead_disc');
init = function() {
rot.addEventListener("mousedown", start, false);
$(document).bind('mousemove', function(event) {
if (active === true) {
event.preventDefault();
rotate(event);
}
});
$(document).bind('mouseup', function(event) {
event.preventDefault();
stop(event);
});
};
start = function(e) {
e.preventDefault();
var bb = this.getBoundingClientRect(),
t = bb.top,
l = bb.left,
h = bb.height,
w = bb.width,
x, y;
center = {
x: l + (w / 2),
y: t + (h / 2)
};
x = e.clientX - center.x;
y = e.clientY - center.y;
startAngle = R2D * Math.atan2(y, x);
return active = true;
};
rotate = function(e) {
e.preventDefault();
var x = e.clientX - center.x,
y = e.clientY - center.y,
d = R2D * Math.atan2(y, x);
rotation = d - startAngle;
return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
};
stop = function() {
angle += rotation;
return active = false;
};
init();
}).call(this);
html {
height: 100%;
overflow: hidden;
}
body {
background: #1c1c1c;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.wrapper {
height: 100%;
max-height: 960px;
width: 100%;
max-width: 960px;
position: relative;
margin: auto;
}
#attack_disc {
background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/1.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 30vw;
max-width: 1124px;
height: 30vw;
max-height: 1124px;
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
transform-origin: 50% 50%;
border-radius: 50%;
}
#course_disc {
background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/2.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 23vw;
max-width: 868px;
height: 23vw;
max-height: 868px;
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
transform-origin: 50% 50%;
border-radius: 50%;
}
#aob_disc {
background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/3.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 15.5vw;
max-width: 592px;
height: 15.5vw;
max-height: 592px;
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
transform-origin: 50% 50%;
border-radius: 50%;
}
#bearing_lead_disc {
background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/4.png');
background-size: cover;
background-repeat: no-repeat;
background-position: center;
width: 23.5vw;
max-width: 884px;
height: 23.5vw;
max-height: 884px;
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
clip-path: url('#my-clip-path');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div id="attack_disc"></div>
<div id="course_disc"></div>
<div id="aob_disc"></div>
<div id="bearing_lead_disc">
<svg class="svg">
<clipPath id="my-clip-path" clipPathUnits="objectBoundingBox"><path d="M0.501,0 C0.556,0,0.555,0.04,0.555,0.04 C0.555,0.099,0.984,0.229,0.994,0.232 S1,0.243,0.999,0.251 C0.976,0.284,0.874,0.421,0.656,0.469 C0.656,0.469,0.648,0.47,0.647,0.474 C0.646,0.48,0.572,0.984,0.57,0.992 C0.569,0.996,0.569,0.999,0.561,0.999 C0.522,1,0.516,1,0.502,1 C0.487,1,0.482,1,0.443,0.999 C0.434,0.999,0.434,0.996,0.433,0.992 C0.432,0.984,0.358,0.48,0.357,0.474 C0.356,0.47,0.347,0.469,0.347,0.469 H0.347 C0.129,0.421,0.027,0.284,0.005,0.251 C0,0.243,0,0.236,0.01,0.232 S0.449,0.099,0.449,0.04 C0.449,0.04,0.447,0,0.502,0"></path></clipPath>
</svg>
</div>
</div>
The problem appears to be that you extracted the shape and converted it to objectBoundingBox coordinates relative to itself. So the objectBoundingBox coords are no longer relative to your attack disc image.
What you can do is apply a transform to the clip path to scale it down to where it should be. By trial and error I worked out an appropriate scaling that gets it to match the shape it is supposed to clip.
transform="translate(0.5,1) scale(0.415,0.52) translate(-0.5,-1)"
.svg {
position: absolute;
width: 0;
height: 0;
}
.clipped {
width: 884px;
height: 884px;
background: turquoise url(https://zuffdaddy.github.io/uboat-attack-disc/images/4.png);
background-size: cover;
-webkit-clip-path: url(#my-clip-path);
clip-path: url(#my-clip-path);
}
<svg class="svg">
<clipPath id="my-clip-path" clipPathUnits="objectBoundingBox"><path d="M0.501,0 C0.556,0,0.555,0.04,0.555,0.04 C0.555,0.099,0.984,0.229,0.994,0.232 S1,0.243,0.999,0.251 C0.976,0.284,0.874,0.421,0.656,0.469 C0.656,0.469,0.648,0.47,0.647,0.474 C0.646,0.48,0.572,0.984,0.57,0.992 C0.569,0.996,0.569,0.999,0.561,0.999 C0.522,1,0.516,1,0.502,1 C0.487,1,0.482,1,0.443,0.999 C0.434,0.999,0.434,0.996,0.433,0.992 C0.432,0.984,0.358,0.48,0.357,0.474 C0.356,0.47,0.347,0.469,0.347,0.469 H0.347 C0.129,0.421,0.027,0.284,0.005,0.251 C0,0.243,0,0.236,0.01,0.232 S0.449,0.099,0.449,0.04 C0.449,0.04,0.447,0,0.502,0" transform="translate(0.5,1) scale(0.415,0.52) translate(-0.5,-1)"></path></clipPath>
</svg>
<div class="clipped"></div>
Svg better to be inside div
Svg better to be inside div so you have more control on the shape and it's also can be scale.
First I fix your path 'd' with this site (https://aydos.com/svgedit/)
Second I put the svg inside the div
Third I order the svg with view box to suitable (with color red some transparent) like the background-image link in 'bearing_lead_disc' and use css pointer-events:none for ignore clicking on the div and then we can rotate the circles even we clicked on the shape.
link: (https://codepen.io/omergal/pen/qBqzeQa)
pic:
///////////////////////////////
// ------- rotate -------- //
///////////////////////////////
(function() {
var init, rotate, start, stop,
active = false,
angle = 0,
rotation = 0,
startAngle = 0,
center = {
x: 0,
y: 0
},
R2D = 180 / Math.PI,
rot = document.getElementById('attack_disc');
init = function() {
rot.addEventListener("mousedown", start, false);
$(document).bind('mousemove', function(event) {
if (active === true) {
event.preventDefault();
rotate(event);
}
});
$(document).bind('mouseup', function(event) {
event.preventDefault();
stop(event);
});
};
start = function(e) {
e.preventDefault();
var bb = this.getBoundingClientRect(),
t = bb.top,
l = bb.left,
h = bb.height,
w = bb.width,
x, y;
center = {
x: l + (w / 2),
y: t + (h / 2)
};
x = e.clientX - center.x;
y = e.clientY - center.y;
startAngle = R2D * Math.atan2(y, x);
return active = true;
};
rotate = function(e) {
e.preventDefault();
var x = e.clientX - center.x,
y = e.clientY - center.y,
d = R2D * Math.atan2(y, x);
rotation = d - startAngle;
return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
};
stop = function() {
angle += rotation;
return active = false;
};
init();
}).call(this);
(function() {
var init, rotate, start, stop,
active = false,
angle = 0,
rotation = 0,
startAngle = 0,
center = {
x: 0,
y: 0
},
R2D = 180 / Math.PI,
rot = document.getElementById('course_disc');
init = function() {
rot.addEventListener("mousedown", start, false);
$(document).bind('mousemove', function(event) {
if (active === true) {
event.preventDefault();
rotate(event);
}
});
$(document).bind('mouseup', function(event) {
event.preventDefault();
stop(event);
});
};
start = function(e) {
e.preventDefault();
var bb = this.getBoundingClientRect(),
t = bb.top,
l = bb.left,
h = bb.height,
w = bb.width,
x, y;
center = {
x: l + (w / 2),
y: t + (h / 2)
};
x = e.clientX - center.x;
y = e.clientY - center.y;
startAngle = R2D * Math.atan2(y, x);
return active = true;
};
rotate = function(e) {
e.preventDefault();
var x = e.clientX - center.x,
y = e.clientY - center.y,
d = R2D * Math.atan2(y, x);
rotation = d - startAngle;
return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
};
stop = function() {
angle += rotation;
return active = false;
};
init();
}).call(this);
(function() {
var init, rotate, start, stop,
active = false,
angle = 0,
rotation = 0,
startAngle = 0,
center = {
x: 0,
y: 0
},
R2D = 180 / Math.PI,
rot = document.getElementById('aob_disc');
init = function() {
rot.addEventListener("mousedown", start, false);
$(document).bind('mousemove', function(event) {
if (active === true) {
event.preventDefault();
rotate(event);
}
});
$(document).bind('mouseup', function(event) {
event.preventDefault();
stop(event);
});
};
start = function(e) {
e.preventDefault();
var bb = this.getBoundingClientRect(),
t = bb.top,
l = bb.left,
h = bb.height,
w = bb.width,
x, y;
center = {
x: l + (w / 2),
y: t + (h / 2)
};
x = e.clientX - center.x;
y = e.clientY - center.y;
startAngle = R2D * Math.atan2(y, x);
return active = true;
};
rotate = function(e) {
e.preventDefault();
var x = e.clientX - center.x,
y = e.clientY - center.y,
d = R2D * Math.atan2(y, x);
rotation = d - startAngle;
return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
};
stop = function() {
angle += rotation;
return active = false;
};
init();
}).call(this);
(function() {
var init, rotate, start, stop,
active = false,
angle = 0,
rotation = 0,
startAngle = 0,
center = {
x: 0,
y: 0
},
R2D = 180 / Math.PI,
rot = document.getElementById('bearing_lead_disc');
init = function() {
rot.addEventListener("mousedown", start, false);
$(document).bind('mousemove', function(event) {
if (active === true) {
event.preventDefault();
rotate(event);
}
});
$(document).bind('mouseup', function(event) {
event.preventDefault();
stop(event);
});
};
start = function(e) {
e.preventDefault();
var bb = this.getBoundingClientRect(),
t = bb.top,
l = bb.left,
h = bb.height,
w = bb.width,
x, y;
center = {
x: l + (w / 2),
y: t + (h / 2)
};
x = e.clientX - center.x;
y = e.clientY - center.y;
startAngle = R2D * Math.atan2(y, x);
return active = true;
};
rotate = function(e) {
e.preventDefault();
var x = e.clientX - center.x,
y = e.clientY - center.y,
d = R2D * Math.atan2(y, x);
rotation = d - startAngle;
return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
};
stop = function() {
angle += rotation;
return active = false;
};
init();
}).call(this);
html {
height: 100%;
overflow: hidden;
}
body {
background: #1c1c1c;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.wrapper {
height: 100%;
max-height: 960px;
width: 100%;
max-width: 960px;
position: relative;
margin: auto;
}
#attack_disc {
background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/1.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 30vw;
max-width: 1124px;
height: 30vw;
max-height: 1124px;
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
transform-origin:50% 50%;
border-radius:50%;
}
#course_disc {
background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/2.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 23vw;
max-width: 868px;
height: 23vw;
max-height: 868px;
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
transform-origin:50% 50%;
border-radius:50%;
}
#aob_disc {
background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/3.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 15.5vw;
max-width: 592px;
height: 15.5vw;
max-height: 592px;
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
transform-origin:50% 50%;
border-radius:50%;
}
#bearing_lead_disc {
background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/4.png');
/* background-color: red; */
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 23.5vw;
max-width: 884px;
height: 23.5vw;
max-height: 884px;
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
clip-path: url('#myPath');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div id="attack_disc"></div>
<div id="course_disc"></div>
<div id="aob_disc"></div>
<div id="bearing_lead_disc" style="pointer-events:none;">
<svg viewBox="0 0 512 512" style="width:100%; height:100%;">
<path style="pointer-events:all;" fill="#ff00004d" d="M255.77 26.76c20 0 19.5 18.5 19.5 18.5 0 27 155.5 86.5 159 88s3.61 5.03 1.78 8.5c-8.07 15.27-45.11 77.9-124.18 99.85 0 0-3.05.81-3.32 2.67-.38 2.6-27.27 233.45-27.88 237.47-.27 1.76-.27 2.84-3.35 2.97-14.18.56-16.1.53-21.37.53s-7.19.03-21.37-.53c-3.08-.12-3.09-1.2-3.35-2.97-.61-4.03-27.5-234.88-27.88-237.47-.27-1.86-3.32-2.69-3.32-2.69-79.01-21.98-116.01-84.57-124.08-99.84-1.83-3.47-1.72-7 1.78-8.5s159-61 159-88c0 0-.5-18.5 19.5-18.5" />
</svg>
</div>
</div>