I need a circle with changeable border length [duplicate] - javascript

This question already has answers here:
Percent pie chart with css only
(3 answers)
Closed 3 years ago.
I want to create a circle that shows percent whit its border length like a
circular diagram but with border.
Like Have you seen https://pasteboard.co/IeLnpWt.jpg

you need svg in your html:
$(document).ready(function(){
$('circle.circle').each(function () {
var percent = Number($(this).data('value'));
var r = parseFloat($(this).css('r'));
var dasharray = parseFloat($(this).css('stroke-dasharray'));
var offset = dasharray - ((Math.PI*2*r) * (percent/100));
$(this).delay(1000).animate({strokeDashoffset: offset}, 1000);
});
});
.wrapper {
position: relative;
width: 60px;
height: 60px;
}
.bar {
position: relative;
transform: rotateZ(-90deg);
width: 60px;
height: 60px;
z-index: 2;
}
.circle {
cx: 50%;
cy: 50%;
r: 28px;
fill: white;
stroke: #0b65bf;
stroke-width: 4px;
stroke-dasharray: calc(3.14 * 56px);
stroke-dashoffset: calc(3.14 * 56px);
}
.border {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #ddd;
border-radius: 50%;
z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg class="bar">
<circle class="circle" data-value="45" />
</svg>

function draw(radius,lineWidth,col,startPerc, endPerc)
{
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");
var posx = radius + lineWidth;
var posy = radius + lineWidth;
var start = -Math.PI/2; // Top of circle (0 would be right side)
context.lineWidth = lineWidth;
context.strokeStyle = col;
context.beginPath();
context.arc(posx, posy, radius, start + (2*Math.PI)*startPerc, start + (2*Math.PI)*endPerc);
context.stroke();
}
draw(30,5,"#2976CD",0,.60);
draw(30,5,"#E0E6E7",.60,1);
<canvas style="border:1px solid gray;" id="imgCanvas" width="100" height="100" onclick="draw()"></canvas>

Related

How do I move the position of canvas using either css or javascript?

this is my first question here. I am fairly new to html, css, and javascript.
What I wanted to achieve was similar to this mockup i've created:
my website mockup
I've tried to replace the rectangle on the left side with javascript code to achieve a similar effect. The javascript code was taken from this codepen:
https://codepen.io/vaaghu/pen/abmYGYz
I've nudged the canvas a bit to the right, but if i extend the canvas width and height, the canvas does extend, but the circle animations don't. How do I extend this animation?
var canvas = document.querySelector("canvas")
canvas.width = 800;
canvas.height = 1600;
var c = canvas.getContext("2d");
var mouse = {x:innerWidth/2,y:innerHeight/2}
window.addEventListener("mousemove",(event)=>{
mouse.x = event.x;
mouse.y = event.y;
})
window.addEventListener("resize",()=>{
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
int();
})
function Circle(x, y,dx,dy,radius,color) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.radius = radius;
this.color = color
var maxRadius = 30;
this.draw = function() {
c.beginPath();
c.arc(this.x,this.y,this.radius,0,Math.PI * 2,false);
c.fillStyle = color
c.fill();
}
this.update = function(){
if(this.x+this.radius > innerWidth || this.x-this.radius < 0) {
this.dx = -this.dx;
}
if(this.y+this.radius > innerHeight || this.y -this.radius < 0 ) {
this.dy = -this.dy;
}
if( mouse.x - this.x > -50 && mouse.x - this.x < 50 && mouse.y - this.y >-50 && mouse.y - this.y < 50) {
if (this.radius < maxRadius) {
this.radius += 1
}
} else {
if (this.radius > radius) {
this.radius -= 1
}
}
this.x += this.dx;
this.y += this.dy;
this.draw();
}
}
var colorArray = ["#F5871A","#81968F","#DFAA2F","#D76034","#F5411D"];
var circleArray = []
function int() {
circleArray = []
for (let i = 0; i < 700; i++) {
var x = Math.random() * window.innerWidth;
var y = Math.random() * (window.innerHeight ) ;
var radius = Math.random() * 5 + 2;
var dx = Math.random() - 0.5;
var dy = Math.random() - 0.5;
var color = colorArray[Math.floor(Math.random()*4)]
circleArray.push(new Circle(x,y,dx,dy,radius,color))
}
}
int()
function animate() {
requestAnimationFrame(animate);
c.clearRect(0,0,innerWidth,innerHeight)
for (let i = 0; i < circleArray.length; i++) {
circleArray[i].update()
}
}
animate();
.mediaViewInfo {
--web-view-name: Homepage;
--web-view-id: Homepage;
--web-scale-on-resize: true;
--web-show-navigation-controls: true;
--web-enable-deep-linking: true;
--web-page-font: arial, Manrope;
}
:root {
--web-view-ids: Homepage;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
border: none;
}
#Homepage {
position: absolute;
width: 100%;
height:450%;
font-family: arial, Manrope;
background-color: rgba(255,255,255,1);
overflow: hidden;
--web-view-name: Homepage;
--web-view-id: Homepage;
--web-scale-on-resize: true;
--web-show-navigation-controls: true;
--web-enable-deep-linking: true;
--web-page-font: arial;
}
canvas {
background: #FFFF05;
background-image: linear-gradient(to bottom, #81968F99, #FFE636CC, #FF000066);
margin: 50% 0% 0% 8%;
padding: 0vh 0vh 0vh 0vh;
z-index:-1;
width:auto;
}
#Wave_Vid {
position: absolute;
left: -19px;
top: -1920px;
width: 100vh;
height: 100vh;
overflow: hidden;
}
.Wave_container {
overflow: visible;
}
#MIDDLEcontainer {
position:absolute;
top: 24%;
left:59%;
}
#MIDDLE {
overflow: visible;
}
#Good_ideas_can_take_time {
line-height: 0.8;
width: 100%;
text-align: left;
padding-right: 10%;
font-family: Manrope, arial;
font-style: normal;
font-weight: bold;
font-size: 15vh;
color: rgba(129,150,143,1);
margin-bottom: 30px;
}
#And_execution_takes_even_more {
width: 100%;
line-height: 1em;
text-align: left;
padding-right: 30vh;
font-family: Manrope, arial;
font-style: normal;
font-weight: normal;
font-size: 5vh;
color: rgba(129,150,143,1);
margin-bottom: 20px;
}
#Line_ {
fill: transparent;
stroke: rgba(129,150,143,1);
stroke-width: 4px;
stroke-linejoin: miter;
stroke-linecap: butt;
stroke-miterlimit: 4;
shape-rendering: auto;
}
.Line_ {
width: 509px;
height: 10px;
transform: matrix(1,0,0,1,0,0);
margin-bottom: 40px;
}
#Midcontainer {
position:absolute;
}
#Mid {
float:bottom;
position:absolute;
}
.MySkills {
position: relative;
overflow:visible;
height: 1em;
text-align: left;
font-family: Manrope, arial;
font-style: normal;
font-weight: lighter;
font-size: 12vh;
color: rgba(129,150,143,1);
letter-spacing: -0.85px;
}
<!DOCTYPE html>
<html>
<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>wbdg portfolio</title>
<link rel="stylesheet" type="text/css" id="applicationStylesheet" href="../faux styles.css"/>
</head>
<body>
<div>
<canvas></canvas>
<script id="jssomething" type="text/javascript" src="../faux scripts.js"></script>
<script src="https://kit.fontawesome.com/4f3ce16e3e.js" crossorigin="anonymous"></script>
<div id="MIDDLEcontainer">
<div id="MIDDLE">
<div id="Good_ideas_can_take_time">
<p>Good ideas can take time.</p>
</div>
<div id="And_execution_takes_even_more">
<span>And execution takes even more.</span>
</div>
<svg class="Line_" viewBox="0 0 674 4">
<path id="Line_" d="M 0 0 L 674 0">
</path>
</svg>
<div id="Midcontainer">
<div id="Mid">
<div class="MySkills"> Photos </div>
<div class="MySkills"> Illustrations </div>
<div class="MySkills"> Videos </div>
<div class="MySkills"> Animations </div>
<div class="MySkills"> Branding </div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
If I understand correctly, change these lines in int() function:
var x = Math.random() * window.innerWidth;
var y = Math.random() * (window.innerHeight ) ;
to this:
var x = Math.random() * canvas.width;
var y = Math.random() * canvas.height;

How can I put Javascript element into CSS background-image

Hi my first javascript project. I wanted to create image in javascript and put it as background for the clock created in css. Everything works great but I don't know how to refer to css .clock so I could put drawn image as background to my css clock (4th line in css file).
I saw other questions but they mostly refer to other javascript drawn images. I want to either add myPiechart.draw as background for css clock or save it as image and set is as background for css clock. Whichever is easier to do. Here you have code below if you copy paste you will see working clock and created image:
html file:
<!DOCTYPE html>
<head>
<link href="styles.css" rel="stylesheet">
<script defer src="script.js"></script>
</head>
<body>
<div class="clock">
<div class="hand hour" data-hour-hand></div>
<div class="hand minute" data-minute-hand></div>
<div class="hand second" data-second-hand></div>
</div>
<canvas id="myCanvas"></canvas>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
javascript file (creating image that I want to be added as background):
var myCanvas = document.getElementById("myCanvas");
myCanvas.width = 300;
myCanvas.height = 300;
var ctx = myCanvas.getContext("2d");
// FUNCTIONS FOR DRAWING CHART
function drawLine(ctx, startX, startY, endX, endY) {
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
ctx.stroke();
}
function drawArc(ctx, centerX, centerY, radius, startAngle, endAngle) {
ctx.beginPath();
ctx.arc(centerX, centerY, radius, startAngle, endAngle);
ctx.stroke();
}
function drawPieSlice(ctx, centerX, centerY, radius, startAngle, endAngle, color) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, radius, startAngle - 1.575, endAngle - 1.575);
ctx.closePath();
ctx.fill();
}
// FUNCTION THAT DRAWS PIE CHART
var Piechart = function (options) {
this.options = options;
this.canvas = options.canvas;
this.ctx = this.canvas.getContext("2d");
this.colors = options.colors;
this.draw = function () {
var total_value = 0;
var color_index = 0;
for (var categ in this.options.data) {
var val = this.options.data[categ];
total_value += val;
}
var start_angle = 0;
for (categ in this.options.data) {
val = this.options.data[categ];
var slice_angle = (2 * Math.PI * val) / total_value;
drawPieSlice(
this.ctx,
this.canvas.width / 2,
this.canvas.height / 2,
Math.min(this.canvas.width / 2, this.canvas.height / 2),
start_angle,
start_angle + slice_angle,
this.colors[color_index % this.colors.length]
);
start_angle += slice_angle;
color_index++;
}
};
};
// DATA
var myData = {
"A": 15,
"B": 25,
"C": 12,
"D": 8,
};
// CREATING NEW PIECHART
var myPiechart = new Piechart({
canvas: myCanvas,
data: myData,
// red orange yellow green ADD more colors if needed
colors: ["#FF0000", "#FFBC00", "#FFFF00", "#00FF00"],
});
myPiechart.draw();
// CLOCK PART
setInterval(setClock, 1000);
const hourHand = document.querySelector("[data-hour-hand]");
const minuteHand = document.querySelector("[data-minute-hand]");
const secondHand = document.querySelector("[data-second-hand]");
function setClock() {
const currentDate = new Date();
const secondsRatio = currentDate.getSeconds() / 60;
const minutesRatio = (secondsRatio + currentDate.getMinutes()) / 60;
const hoursRatio = (minutesRatio + currentDate.getHours()) / 12;
setRotation(secondHand, secondsRatio);
setRotation(minuteHand, minutesRatio);
setRotation(hourHand, hoursRatio);
}
function setRotation(element, rotationRatio) {
element.style.setProperty("--rotation", rotationRatio * 360);
}
setClock();
css file (clock):
.clock {
width: 300px;
height: 300px;
/*background-image: url("piechart.png"); *//*HERE I WANT TO ADD PIECHART IMAGE*/
border-radius: 50%;
border: 2px solid black;
position: relative;
}
.clock .number {
--rotation: 0;
position: absolute;
width: 100%;
height: 100%;
text-align: center;
transform: rotate(var(--rotation));
font-size: 1.5rem;
}
.clock .hand {
--rotation: 0;
position: absolute;
bottom: 50%;
left: 50%;
border: 1px solid white;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
transform-origin: bottom;
z-index: 10;
transform: translateX(-50%) rotate(calc(var(--rotation) * 1deg));
}
.clock::after {
content: "";
position: absolute;
background-color: black;
z-index: 11;
width: 15px;
height: 15px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
}
.clock .hand.second {
width: 3px;
height: 45%;
background-color: red;
}
.clock .hand.minute {
width: 7px;
height: 40%;
background-color: black;
}
.clock .hand.hour {
width: 10px;
height: 35%;
background-color: black;
}
If there are better ways to do this I'm open to suggestions.
Place element canvas#myCanvas as a child of div.clock
<div class="clock">
<div class="hand hour" data-hour-hand></div>
<div class="hand minute" data-minute-hand></div>
<div class="hand second" data-second-hand></div>
<canvas id="myCanvas"></canvas>
</div>

Make an indicator move around a circle

I was trying to come up with some JS (pure JS) code making the indicator move around the circle while the pin is being moved (as if it was a speedometer), but I failed. I tried to use offsets, count the offsetTop etc., but it doesn't work. Can anyone help me out here, please?
If there is some other way to do this without using some extra libraries (for example, just using the css options), let me know - I'll be really grateful as it's really important for me to understand the concept here!
'use strict';
let firstIndicator = document.querySelector('.indicator');
let pinLevel = document.querySelector('.effect-level__pin');
let effectLevelLine = document.querySelector('.effect-level__line');
let effectLevelDepth = document.querySelector('.effect-level__depth');
let changeOverlay = function (percentage) {
pinLevel.style.left = percentage + '%';
effectLevelDepth.style.width = percentage + '%';
};
pinLevel.addEventListener('mousedown', function (evt) {
evt.preventDefault();
let startX = evt.clientX;
let startLevelDepthWidth = effectLevelDepth.offsetWidth;
let clickedPercentageLevel = startLevelDepthWidth / effectLevelLine.offsetWidth * 100;
changeOverlay(clickedPercentageLevel);
let onMouseMove = function (moveEvt) {
moveEvt.preventDefault();
let shift = moveEvt.clientX - startX;
let levelWidth = startLevelDepthWidth + shift;
let movedPercentageLevel = levelWidth / effectLevelLine.offsetWidth * 100;
movedPercentageLevel = Math.max(0, movedPercentageLevel);
movedPercentageLevel = Math.min(100, movedPercentageLevel);
changeOverlay(movedPercentageLevel);
firstIndicator.style.top = (firstIndicator.offsetHeight * 3) - (movedPercentageLevel / 100) + 'px';
firstIndicator.style.transform = 'rotate('+ (52 + movedPercentageLevel * 2.4) + 'deg' + ')';
};
let onMouseUp = function (upEvt) {
upEvt.preventDefault();
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
.circle {
margin: 0 auto;
margin-top: 50px;
width: 150px;
height: 150px;
border: 1px solid black;
border-radius: 50%
}
.indicator {
position: relative;
}
.indicator svg {
position: absolute;
top: -100px;
transform: rotate(82deg);
left: 108px;
}
.effect-level {
position: absolute;
bottom: -30px;
left: 50%;
width: 495px;
height: 33px;
font-size: 12px;
line-height: 42px;
text-align: center;
color: black;
white-space: nowrap;
background-color: #ffffff;
border: none;
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
transform: translateX(-50%);
}
.effect-level__value {
display: none;
}
.effect-level__line {
position: absolute;
top: 50%;
right: 20px;
left: 20px;
height: 5px;
font-size: 0;
background-color: rgba(0, 0, 0, 0.2);
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
.effect-level__pin {
position: absolute;
top: 50%;
left: 0%;
z-index: 1;
width: 18px;
height: 18px;
margin: -9px 0 0;
background-color: #fff;
border-radius: 50%;
border: 1px solid #323232;
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
transform: translateX(-50%);
cursor: move;
}
.effect-level__depth {
position: absolute;
width: 0%;
height: 100%;
background-color: #323232;
}
<div class="circle"></div>
<div class="indicator">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="337.0744522647706 304.4241607573019 28.925547735229372 104" width="24.93" height="100"><defs><path d="" id="c6VRx4235S"></path><path d="M348.07 305.42L338.07 405.42" id="f84HmfmJk"></path><path d="M340.01 305.42L338.07 403.88" id="azVXtGrDR"></path></defs><g><g><g><use xlink:href="#c6VRx4235S" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#f84HmfmJk" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#azVXtGrDR" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g></g>
</svg>
</div>
<fieldset class="effect-level">
<input class="effect-level__value" type="number" name="effect-level" value="0">
<div class="effect-level__line">
<div class="effect-level__pin" tabindex="0">Кнопка изменения эффекта </div>
<div class="effect-level__depth">Глубина эффекта</div>
</div>
</fieldset>
You can define the size of your .indicator such that, when rotated using transform: rotate(angle), it rotates about the center of your defined circle.
It's always better to define your moving elements & their references as position: absolute and later have container divs to place it where ever you want.
.circle {
position: absolute;
top: 100px;
left: 100px;
width: 150px;
height: 150px;
border: 1px solid black;
border-radius: 50%;
}
.indicator {
position: absolute;
top: 6px;
left: 155px;
height: 340px;
width: 44px;
transform: rotate(0deg);
}
.indicator svg {
transform: rotate(177deg);
}
This makes our lives very easy, we just have to rotate .indicator based on your movedPercentageLevel.
Check out the following code snippet.
'use strict';
let firstIndicator = document.querySelector('.indicator');
let pinLevel = document.querySelector('.effect-level__pin');
let effectLevelLine = document.querySelector('.effect-level__line');
let effectLevelDepth = document.querySelector('.effect-level__depth');
let changeOverlay = function(percentage) {
pinLevel.style.left = percentage + '%';
effectLevelDepth.style.width = percentage + '%';
};
pinLevel.addEventListener('mousedown', function(evt) {
evt.preventDefault();
let startX = evt.clientX;
let startLevelDepthWidth = effectLevelDepth.offsetWidth;
let clickedPercentageLevel = startLevelDepthWidth / effectLevelLine.offsetWidth * 100;
changeOverlay(clickedPercentageLevel);
let onMouseMove = function(moveEvt) {
moveEvt.preventDefault();
let shift = moveEvt.clientX - startX;
let levelWidth = startLevelDepthWidth + shift;
let movedPercentageLevel = levelWidth / effectLevelLine.offsetWidth * 100;
movedPercentageLevel = Math.max(0, movedPercentageLevel);
movedPercentageLevel = Math.min(100, movedPercentageLevel);
changeOverlay(movedPercentageLevel);
firstIndicator.style.transform = 'rotate(' + movedPercentageLevel * 3.6 + 'deg' + ')';
};
let onMouseUp = function(upEvt) {
upEvt.preventDefault();
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
.circle {
position: absolute;
top: 100px;
left: 100px;
width: 150px;
height: 150px;
border: 1px solid black;
border-radius: 50%;
}
.indicator {
position: absolute;
top: 6px;
left: 155px;
height: 340px;
width: 44px;
transform: rotate(0deg);
}
.indicator svg {
transform: rotate(177deg);
}
.effect-level {
position: absolute;
bottom: -30px;
left: 50%;
width: 495px;
height: 33px;
font-size: 12px;
line-height: 42px;
text-align: center;
color: black;
white-space: nowrap;
background-color: #ffffff;
border: none;
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
transform: translateX(-50%);
}
.effect-level__value {
display: none;
}
.effect-level__line {
position: absolute;
top: 50%;
right: 20px;
left: 20px;
height: 5px;
font-size: 0;
background-color: rgba(0, 0, 0, 0.2);
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
.effect-level__pin {
position: absolute;
top: 50%;
left: 0%;
z-index: 1;
width: 18px;
height: 18px;
margin: -9px 0 0;
background-color: #fff;
border-radius: 50%;
border: 1px solid #323232;
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
transform: translateX(-50%);
cursor: move;
}
.effect-level__depth {
position: absolute;
width: 0%;
height: 100%;
background-color: #323232;
}
<div class="circle"></div>
<div class="indicator">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="337.0744522647706 304.4241607573019 28.925547735229372 104" width="24.93" height="100"><defs><path d="" id="c6VRx4235S"></path><path d="M348.07 305.42L338.07 405.42" id="f84HmfmJk"></path><path d="M340.01 305.42L338.07 403.88" id="azVXtGrDR"></path></defs><g><g><g><use xlink:href="#c6VRx4235S" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#f84HmfmJk" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#azVXtGrDR" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g></g>
</svg>
</div>
<fieldset class="effect-level">
<input class="effect-level__value" type="number" name="effect-level" value="0">
<div class="effect-level__line">
<div class="effect-level__pin" tabindex="0">Кнопка изменения эффекта </div>
<div class="effect-level__depth">Глубина эффекта</div>
</div>
</fieldset>
Just for fun, here's an even more javascript-y flavour that doesn't need any elements rotating. Just a circle and a line, redrawn to new coordinates after rotation about a point.
Here it just updates on mouse movement but desired angle just needs to be fed into the function as an offset.
'use strict';
// get the canvas element
const canvas = document.getElementById('canvas');
canvas.width = 170;
canvas.height = 170;
canvas.style.background = 'red';
canvas.style.border = '1px solid black';
// somewhere to store the position and state of the needle
const needle = {
start_angle: 0,
current_angle: 0,
point_x: canvas.width,
point_y: canvas.height/2 // the 3oclock position is just straight to the right! from the centre of our circle,
}
// handy function to rotate a point about a point. first google result
const rotatePoint = (x, y, centerx, centery, degrees)=>{ // https://stackoverflow.com/a/45649110/2244284
let newx = (x - centerx) * Math.cos(degrees * Math.PI / 180) - (y - centery) * Math.sin(degrees * Math.PI / 180) + centerx;
let newy = (x - centerx) * Math.sin(degrees * Math.PI / 180) + (y - centery) * Math.cos(degrees * Math.PI / 180) + centery;
return [newx, newy];
}
// handy function to convert degrees to radians
const d2r = (degree)=>{
return degree * (Math.PI / 180);
}
// handy function to draw a circle
const drawCircle = ()=>{
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(canvas.width/2, canvas.height/2, canvas.width/2, 0, d2r(360)); // just use the whole canvas
ctx.stroke();
}
// draw our needle
const drawNeedle = (offset)=>{
let xy = rotatePoint(needle.point_x, needle.point_y, canvas.width/2, canvas.height/2, offset); // point_x/y is the far end of the needle, the other side is just the centre of the circle/canvas
// draw a line from centre to the new point of the needle
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(canvas.width/2, canvas.height/2);
ctx.lineTo(xy[0], xy[1]);
ctx.stroke();
}
// --- init stuff
drawCircle(); // draw first circle
drawNeedle(needle.start_angle); // draw first needle
// add an event for every mouse move detected over the canvas
canvas.addEventListener('mousemove', (e)=>{
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height); // clear clear the canvas
drawCircle(); // redraw the circle
let offset = needle.start_angle + needle.current_angle++ % 360; // increase angle by 1 for every mouseover event, reset to 0 if a full circle is reached
drawNeedle(offset) // draw needle
})
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>

Fill in overlapping circle area

I have two circles that intersect and I want to make the intersecting area have a color, even when the two circles are transparent. I thought I could find some way to do this with css mix-blend-mode property but I have had no success with it.
Of course, I could make the circles have color and decrease their opacity, but I want them to be either white or transparent, where only the overlapped area gets background color.
I want the intersecting area to be able to change dynamically because one circle will follow the mouse.
Here is the codepen for that.
I'm not sure where to start on this, if css has some technique or if it will have to be done with jquery.
$(document).mousemove(function(e) {
$('.cursor').eq(0).css({
left: e.pageX - 25,
top: e.pageY - 20
});
// circles
var c1 = $('.cursor');
var c2 = $('.circle');
// radius
var d1 = c1.outerWidth(true)/2;
var d2 = c2.outerWidth(true)/2;
// centers of first circle
var x1 = c1.offset().left + c1.width()/2;
var y1 = c1.offset().top + c1.height()/2;
// centers of second circle
var x2 = c2.offset().left + c2.width()/2;
var y2 = c2.offset().top + c2.height()/2;
var i1 = c2.find('.inter1');
var i2 = c2.find('.inter2');
var o = c1.find('.overlap');
function calc() {
var a = d2;
var b = d1;
var c = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
var d = (b*b+c*c-a*a)/(2*c);
var h = Math.sqrt((b*b) - (d*d));
if (d < 0 || $.isNumeric(h)) {
c2.css('border-color', 'red');
} else {
c2.css('border-color', 'black');
}
var x3 = (x2-x1)*d/c + (y2-y1)*h/c + x1;
var y3 = (y2-y1)*d/c - (x2-x1)*h/c + y1;
var x4 = (x2-x1)*d/c - (y2-y1)*h/c + x1;
var y4 = (y2-y1)*d/c + (x2-x1)*h/c + y1;
if ($.isNumeric(h)) {
i1.show();
i2.show();
} else {
i1.hide();
i2.hide();
}
i1.offset({ top: y3-5, left: x3-5});
i2.offset({ top: y4-5, left: x4-5});
} calc();
});
body {
background: #fff;
}
.overlap {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0, 0, 0, 0.5);
}
.cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
z-index: 999;
border: 1px solid black;
outline: 1px solid #c9d3ff;
overflow: none;
}
.circle {
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border: 1px solid black;
outline: 1px solid #c9d3ff;
}
.circle::after,
.cursor::after {
display: block;
content: '';
height: 1px;
background: #c9d3ff;
position: absolute;
top: 50%;
left: 0;
right: 0;
}
.circle::before,
.cursor::before {
display: block;
content: '';
width: 1px;
background: #c9d3ff;
position: absolute;
left: 50%;
top: 0;
bottom: 0;
}
.inter {
width: 10px;
height: 10px;
background: black;
border-radius: 50%;
position: absolute;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cursor">
</div>
<div class="circle">
<div class="inter1 inter"></div>
<div class="inter2 inter"></div>
<div>
One way you can approach this is by adding a "inner-cursor" circle inside the main circle. Based on mouse movement it will move with the main cursor given the illusion of overlap.
In this case, the background color of the intersecting circles will not matter. Also, you do not have to worry about mix-blend-mode since the inner cursor has a background color and is hidden. It is only viewed if the mouse hovers over the main circle.
See this example:
$(document).mousemove(function(e) {
// elements
let cursor = $('.cursor');
let innerCursor = $('.inner-cursor');
let c2 = $('.circle');
let pos = {
left: e.pageX - 25,
top: e.pageY - 20
};
cursor.css(pos);
innerCursor.css({
left: pos.left - c2.offset().left,
top: pos.top - c2.offset().top
});
// circles
// radius
var d1 = cursor.outerWidth(true) / 2;
var d2 = c2.outerWidth(true) / 2;
// centers of first circle
var x1 = cursor.offset().left + cursor.width() / 2;
var y1 = cursor.offset().top + cursor.height() / 2;
// centers of second circle
var x2 = c2.offset().left + c2.width() / 2;
var y2 = c2.offset().top + c2.height() / 2;
var i1 = c2.find('.inter1');
var i2 = c2.find('.inter2');
var o = cursor.find('.overlap');
function calc() {
var a = d2;
var b = d1;
var c = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
var d = (b * b + c * c - a * a) / (2 * c);
var h = Math.sqrt((b * b) - (d * d));
// console.log(a, b, c, d, h);
if (d < 0 || $.isNumeric(h)) {
c2.css('border-color', 'red');
} else {
c2.css('border-color', 'black');
}
var x3 = (x2 - x1) * d / c + (y2 - y1) * h / c + x1;
var y3 = (y2 - y1) * d / c - (x2 - x1) * h / c + y1;
var x4 = (x2 - x1) * d / c - (y2 - y1) * h / c + x1;
var y4 = (y2 - y1) * d / c + (x2 - x1) * h / c + y1;
if ($.isNumeric(h)) {
i1.show();
i2.show();
} else {
i1.hide();
i2.hide();
}
i1.offset({
top: y3 - 5,
left: x3 - 5
});
i2.offset({
top: y4 - 5,
left: x4 - 5
});
}
calc();
});
body {
background: #fff;
}
.clip {
display: inline-block;
background: blue;
height: 50px;
width: 50px;
border-radius: 50%;
clip-path: ellipse(50px 50px at 50% 0%);
position: absolute;
left: 750px;
top: 40px;
}
.cursor {
left: 750px;
top: 40px;
}
.cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
z-index: 999;
border: 1px solid black;
outline: 1px solid #c9d3ff;
overflow: none;
mix-blend-mode: multiply;
background: rgba(100, 100, 100, 0.1);
}
.circle {
background: rgba(100, 100, 100, 0.1);
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border: 1px solid black;
outline: 1px solid #c9d3ff;
overflow: hidden;
}
.circle::after,
.cursor::after {
display: block;
content: '';
height: 1px;
background: #c9d3ff;
position: absolute;
top: 50%;
left: 0;
right: 0;
}
.circle::before,
.cursor::before {
display: block;
content: '';
width: 1px;
background: #c9d3ff;
position: absolute;
left: 50%;
top: 0;
bottom: 0;
}
.inter {
width: 10px;
height: 10px;
background: black;
border-radius: 50%;
position: absolute;
display: none;
}
.inner-cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
background: green;
left: 50%;
top: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cursor">
</div>
<span class="clip"></span>
<div class="circle">
<div class='inner-cursor'></div>
<div class="inter1 inter"></div>
<div class="inter2 inter"></div>
</div>
On easy idea using only CSS is to consider a radial-gradient as background using background-attachement:fixed. You apply this background to the cursor element and you make its dimension/position the same as the fixed element.
All you need to add in your code is:
background:radial-gradient(circle,blue 100px,transparent 100px) fixed no-repeat
I have also optimized the code to remove the line you draw with pseudo element to consider linear-gradient
$(document).mousemove(function(e) {
$('.cursor').eq(0).css({
left: e.pageX - 25,
top: e.pageY - 20
});
// circles
var c1 = $('.cursor');
var c2 = $('.circle');
// radius
var d1 = c1.outerWidth(true)/2;
var d2 = c2.outerWidth(true)/2;
// centers of first circle
var x1 = c1.offset().left + c1.width()/2;
var y1 = c1.offset().top + c1.height()/2;
// centers of second circle
var x2 = c2.offset().left + c2.width()/2;
var y2 = c2.offset().top + c2.height()/2;
var i1 = c2.find('.inter1');
var i2 = c2.find('.inter2');
var o = c1.find('.overlap');
function calc() {
var a = d2;
var b = d1;
var c = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
var d = (b*b+c*c-a*a)/(2*c);
var h = Math.sqrt((b*b) - (d*d));
if (d < 0 || $.isNumeric(h)) {
c2.css('border-color', 'red');
} else {
c2.css('border-color', 'black');
}
var x3 = (x2-x1)*d/c + (y2-y1)*h/c + x1;
var y3 = (y2-y1)*d/c - (x2-x1)*h/c + y1;
var x4 = (x2-x1)*d/c - (y2-y1)*h/c + x1;
var y4 = (y2-y1)*d/c + (x2-x1)*h/c + y1;
if ($.isNumeric(h)) {
i1.show();
i2.show();
} else {
i1.hide();
i2.hide();
}
i1.offset({ top: y3-5, left: x3-5});
i2.offset({ top: y4-5, left: x4-5});
} calc();
});
body {
background: #fff;
margin:0;
}
*{
box-sizing:border-box;
}
.cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
z-index: 999;
border: 1px solid black;
outline: 1px solid #c9d3ff;
background:
linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px,
linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%,
radial-gradient(circle,blue 100px,transparent 101px) fixed,
yellow;
background-repeat:no-repeat;
}
.circle {
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border: 1px solid black;
outline: 1px solid #c9d3ff;
background:
linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px,
linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%,
#f2f2f2;
background-repeat:no-repeat;
}
.inter {
width: 10px;
height: 10px;
background: black;
border-radius: 50%;
position: absolute;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cursor">
</div>
<div class="circle">
<div class="inter1 inter"></div>
<div class="inter2 inter"></div>
<div>
And if the circle is not in the middle you simply adjust the position.
$(document).mousemove(function(e) {
$('.cursor').eq(0).css({
left: e.pageX - 25,
top: e.pageY - 20
});
// circles
var c1 = $('.cursor');
var c2 = $('.circle');
// radius
var d1 = c1.outerWidth(true)/2;
var d2 = c2.outerWidth(true)/2;
// centers of first circle
var x1 = c1.offset().left + c1.width()/2;
var y1 = c1.offset().top + c1.height()/2;
// centers of second circle
var x2 = c2.offset().left + c2.width()/2;
var y2 = c2.offset().top + c2.height()/2;
var i1 = c2.find('.inter1');
var i2 = c2.find('.inter2');
var o = c1.find('.overlap');
function calc() {
var a = d2;
var b = d1;
var c = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
var d = (b*b+c*c-a*a)/(2*c);
var h = Math.sqrt((b*b) - (d*d));
if (d < 0 || $.isNumeric(h)) {
c2.css('border-color', 'red');
} else {
c2.css('border-color', 'black');
}
var x3 = (x2-x1)*d/c + (y2-y1)*h/c + x1;
var y3 = (y2-y1)*d/c - (x2-x1)*h/c + y1;
var x4 = (x2-x1)*d/c - (y2-y1)*h/c + x1;
var y4 = (y2-y1)*d/c + (x2-x1)*h/c + y1;
if ($.isNumeric(h)) {
i1.show();
i2.show();
} else {
i1.hide();
i2.hide();
}
i1.offset({ top: y3-5, left: x3-5});
i2.offset({ top: y4-5, left: x4-5});
} calc();
});
body {
background: #fff;
margin:0;
}
*{
box-sizing:border-box;
}
.cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
z-index: 999;
border: 1px solid black;
outline: 1px solid #c9d3ff;
background:
linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px,
linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%,
radial-gradient(circle at 20% 50%,blue 100px,transparent 101px) fixed
yellow;
background-repeat:no-repeat;
}
.circle {
border-radius: 50%;
position: absolute;
top: 50%;
left: 20%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border: 1px solid black;
outline: 1px solid #c9d3ff;
background:
linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px,
linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%,
#f2f2f2;
background-repeat:no-repeat;
}
.inter {
width: 10px;
height: 10px;
background: black;
border-radius: 50%;
position: absolute;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cursor">
</div>
<div class="circle">
<div class="inter1 inter"></div>
<div class="inter2 inter"></div>
<div>
We basically use the same value of top/left to have the following:
radial-gradient(circle at [left] [top],blue [radius],transparent [radius]);
I add 1px to transparent to avoid the jagged edge
If you feel comfortable with HTML <canvas> element it's probably your best friend for this type of task, I doubt there's a CSS way to achieve what you want.
(If there is a CSS way, it's probably going to be lot more complicated and have much slower perfomance than doing it with canvas anyway)
You can take a look at the code below to be inspired (source and live example)
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body data-rsssl=1>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var offset = 50;
/*
* save() allows us to save the canvas context before
* defining the clipping region so that we can return
* to the default state later on
*/
context.save();
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.clip();
// draw blue circle inside clipping region
context.beginPath();
context.arc(x - offset, y - offset, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'blue';
context.fill();
// draw yellow circle inside clipping region
context.beginPath();
context.arc(x + offset, y, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'yellow';
context.fill();
// draw red circle inside clipping region
context.beginPath();
context.arc(x, y + offset, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'red';
context.fill();
/*
* restore() restores the canvas context to its original state
* before we defined the clipping region
*/
context.restore();
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.lineWidth = 10;
context.strokeStyle = 'blue';
context.stroke();
</script>
</body>
</html>

How to draw a rectangle manually in html without canvas?

What I mean is understood better in this photo
In the given photo, I used canvas for drawings; however, I would like to do it by an another way because I want to created rectangles be draggable and give ids to created rectangles. For example, If I used div instead of canvas, I could not manually draw the rectangles like in the photo. Maybe, there is a way but I don't know it. When I searched this subject, most of the people use paper.js, etc. but it is just useful in resize or drag&drop; therefore, I did not want to use these.
function lettersOnly(input) {
var regex = /[^a-z]/gi;
input.value = input.value.replace(regex, "");
}
jQuery(document).ready(function($) {
//Canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//Variables
var canvasOffset = $("#canvas").offset();
var canvasx = canvasOffset.left;
var canvasy = canvasOffset.top;
var last_mousex = 0;
var last_mousey = 0;
var mousex = 0;
var mousey = 0;
var mousedown = false;
var shapes = [];
var width;
var height;
// make var col a global variable
var col = "black";
var ad = "";
//Mousedown
$(canvas).on('mousedown', function(e) {
last_mousex = parseInt(e.clientX - canvasx);
last_mousey = parseInt(e.clientY - canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function(e) {
const lastPos = {
lastMouseX: last_mousex,
lastMouseY: last_mousey,
rectWidth: width,
rectHeight: height,
// save the color of the rect
color: col,
name: ad
};
shapes.push(lastPos);
mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function(e) {
mousex = parseInt(e.clientX - canvasx);
mousey = parseInt(e.clientY - canvasy);
if (mousedown) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
width = mousex - last_mousex;
height = mousey - last_mousey;
col = $("#color").val();
ad = $("#name").val();
if (shapes.length > 0) {
for (var i in shapes) {
// for every shape in the shapes array beginPath
ctx.beginPath();
//set the color of the stroke
ctx.strokeStyle = shapes[i].color;
//draw the rect
ctx.rect(shapes[i].lastMouseX, shapes[i].lastMouseY, shapes[i].rectWidth, shapes[i].rectHeight);
ctx.fillText(shapes[i].name, shapes[i].rectWidth - shapes[i].lastMouseX, shapes[i].rectHeight - shapes[i].lastMouseY);
ctx.stroke();
}
}
//for the new rect beginPath
ctx.beginPath();
ctx.rect(last_mousex, last_mousey, width, height);
ctx.strokeStyle = col;
ctx.lineWidth = 3;
ctx.fillText(ad, 100, 100);
ctx.stroke();
}
$('#output').html('Current Coordinate: ' + mousex + ', ' + mousey + '<br/>Last Coordinate: ' + last_mousex + ', ' + last_mousey);
});
});
.topnav {
background-color: #333;
overflow: hidden;
}
/* Style the links inside the navigation bar */
.topnav a {
float: left;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 14px;
}
/* Change the color of links on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
}
/* Add a color to the active/current link */
.topnav a.active {
background-color: #4CAF50;
color: white;
}
#color {
border: 1px solid black;
font-family: 'Times New Roman', Times, serif;
font-size: 14px;
margin: auto;
padding: 0;
position: absolute;
top: 0;
left: 45%;
right: 0;
text-align: center;
}
#name {
border: 1px solid black;
font-family: 'Times New Roman', Times, serif;
font-size: 14px;
margin: auto;
padding: 0;
position: absolute;
top: 0;
left: 45%;
right: 0;
text-align: center;
}
.submit {
border: 1px solid black;
margin: auto;
padding: 0;
width: 70px;
height: 30px;
position: absolute;
top: 0;
left: 0;
right: 0;
font-family: 'Times New Roman', Times, serif;
font-size: 14px;
text-align: center;
}
#canvas {
cursor: crosshair;
background-image: url("kroki2v3.png");
background-repeat: no-repeat;
background-size: contain;
padding: 0;
margin-left: 210;
margin-top: 160;
position: static;
display: block;
}
#output {
font-family: 'Times New Roman', Times, serif;
font-size: 14px;
top: 19%;
left: 46%;
position: absolute;
}
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div>
<table>
<tr>
<td><input type="text" id="color" style="margin-top: 70px" placeholder="Color" onkeyup="lettersOnly(this)" /></td>
<td><input type="text" id="name" style="margin-top: 100px;" placeholder="Department Name" onkeyup="lettersOnly(this)" /></td>
<td><input type="submit" class="submit" value="Submit" style="margin-top: 130px;" /></td>
</tr>
</table>
</div>
<div class="topnav">
<a class="active" href="">Project</a>
Contact
About
</div>
<div id="container" style="display: none;"><img src="kroki2v3.png" id="img01" alt="" style="display: none;"></div>
<canvas id="canvas" width="1200" height="520"></canvas>
<div id="output"></div>
</body>
</html>
Something like this? When you say "draw", this is what I imagined.
You need to find the mouse position in the mousedown function and in the mousemove function, then subtract the mousedown x and y position from the mousemove x and y position to set the width and height.
You also need to set a variable to tell whether or not the mouse is actually down while moving the mouse to ensure a div isn't "drawn" without knowledge.
Once you "mouseup" you can set your draggable / resizable functions to be used.
Here is a fiddle;
$(function() {
var widget;
var x;
var y;
var finX;
var finY;
var ismousedown = false;
$(document).on({
mousedown: function(event) {
if ($(event.target).attr('class') == 'wrapper') {
x = event.pageX;
y = event.pageY;
$('body').append('<div class="widget" style="top:' + y + 'px; left: ' + x + 'px;"></div>');
widget = $('.widget').last();
ismousedown = true;
}
},
mousemove: function(event) {
if (ismousedown == true) {
finX = event.pageX;
finY = event.pageY;
widget.width(finX - x);
widget.height(finY - y);
widget.css({
'width': (finX - x) + '!important',
'height': (finY - y) + '!important',
'display': 'block',
'border': '2px dashed #ccc'
});
}
},
mouseup: function(event) {
ismousedown = false;
widget.css({
'background': '#222',
'border': '0',
'cursor': 'move'
});
initDraggable();
}
});
// in case you need to reinitialize later.
function initDraggable() {
$('.widget').draggable({});
}
});
html,
body {
height: 100% !important;
position: relative;
}
.wrapper {
position: relative;
height: 100% !important;
width: 100% !important;
}
.widget {
display: block;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="wrapper">
</div>

Categories

Resources