Make a draggable HTML5 canvas curve area - html

If I have a canvas in which an image is drawn. The image has four points in the curve. I need to make this curve area draggable.
but without use of kinetic Js
Image attached.
HTML
<div id='curveAreaDrag' class="ui-widget-content" >
<div id="point1" class="ui-widget-content"></div>
<div id="point2" class="ui-widget-content"></div>
<div id="point3" class="ui-widget-content"></div>
<div id="point4" class="ui-widget-content"></div>
</div>
<canvas id="myCanvas" width="400px" height="400px"
style="border:1px solid #d3d3d3;top:0;left:0"></canvas>
jQuery
$("#curveAreaDrag").draggable({drag:function(){save();}});
Updated:
I have four points of bezier curve. i am also scaling each point then the light black area also scaling.
i need to drag the light black area. it is not an image. it is selected area by bezier curve.

[ Edited: To fit OP’s additional information ]
This code uses 2 Cubic Bezier Curves and 6 control handles to let you select the eyeball in your image.
The Red handles control the curve on the top part of the eye. The Blue handles control the curve on the bottom part of the eye. The White handles let you anchor on the corners of the eye. The Orange shows the resulting path (=2 curves).
Below is a picture of the app and here is a Fiddle of it in action: http://jsfiddle.net/m1erickson/98G9F/
Here is the code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.1/jquery-ui.js"></script>
<style>
body { font-family: arial; }
.anchor { background: #fff; position: absolute; display: block; height: 10px; width: 10px; border: 1px solid #333; border-radius:5px;}
.control { background: #fff; position: absolute; display: block; height: 20px; width: 20px; border: 1px solid #333; border-radius:10px;}
.p1, .p2 { background: red; z-index: 50; }
.p3, .p4 { background: blue; }
.pStart { background:white;}
.pEnd {background:white;}
.pStart { left: 54px; top: 166px; }
.pEnd { left: 346px; top: 189px; }
.p1 { left: 150px; top: 39px; }
.p2 { left: 276px; top: 97px; }
.p3 { left: 219px; top: 227px; }
.p4 { left: 147px; top: 224px; }
canvas { border: 1px solid #333;}
#start,#end2{color:green;}
#end1{color:purple;}
#c1,#c3{color:red;}
#c2,#c4{color:blue;}
</style>
</head>
<body>
<canvas height="400" width="400" id="canvas"></canvas>
<p>context.moveTo(
<span id="start"></span>);
</p>
<p>context.bezierCurveTo(
<span id="c1"></span>,
<span id="c2"></span>,
<span id="end1"></span>);
</p>
<p>context.bezierCurveTo(
<span id="c3"></span>,
<span id="c4"></span>,
<span id="end2"></span>);
</p>
<script>
var $p1,$p2,$codeMove,$codeBez1,$codeBez2;
$(function() {
var canvas=document.getElementById("canvas");
var ctx = canvas.getContext("2d");
$pStart=$(".pStart");
$pEnd=$(".pEnd");
$p1 = $(".p1");
$p2 = $(".p2");
$p3 = $(".p3");
$p4 = $(".p4");
$codeMove=$("code-move");
$codeBez1=$("code-bez1");
$codeBez2=$("code-bez2");
$(".pStart, .pEnd, .p1, .p2, .p3, .p4").draggable({
containment: 'parent',
drag: function(event, ui) { renderWrap(ctx); },
stop: function(){ renderWrap(ctx); }
});
var eyeImage=new Image();
eyeImage.onload=function(){
canvas.width=eyeImage.width*1.5;
canvas.height=eyeImage.height*1.5;
renderWrap(ctx);
}
eyeImage.src="http://i.stack.imgur.com/SbcL4.png";
function renderWrap(ctx) {
var pStart=$pStart.position();
var pEnd=$pEnd.position();
var p1 = $p1.position();
var p2 = $p2.position();
var p3 = $p3.position();
var p4 = $p4.position();
render({x:pStart.left, y:pStart.top}, {x:pEnd.left, y:pEnd.top}, {x:p1.left, y:p1.top}, {x:p2.left, y:p2.top}, {x:p3.left, y:p3.top}, {x:p4.left, y:p4.top} );
};
function render(start, end, p1, p2, p3, p4) {
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(eyeImage,0,0,eyeImage.width,eyeImage.height,0,0,eyeImage.width*1.5,eyeImage.height*1.5);
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = "orange";
// start-->end
ctx.moveTo(start.x,start.y);
ctx.bezierCurveTo(p1.x,p1.y,p2.x,p2.y,end.x,end.y);
ctx.stroke();
// end-->start
ctx.bezierCurveTo(p3.x,p3.y,p4.x,p4.y,start.x,start.y);
ctx.stroke();
ctx.closePath();
// connectors
ctx.beginPath();
ctx.strokeStyle = "#999";
ctx.lineWidth = 1;
connector(start,p1);
connector(end,p2);
connector(end,p3);
connector(start,p4);
ctx.closePath();
// display code
$("#start").html(start.x+","+start.y);
$("#c1").html(p1.x+","+p1.y);
$("#c2").html(p2.x+","+p2.y);
$("#end1").html(end.x+","+end.y);
$("#c3").html(p3.x+","+p3.y);
$("#c4").html(p4.x+","+p4.y);
$("#end2").html(start.x+","+start.y);
}
function connector(pt1,pt2){
ctx.moveTo(pt1.x,pt1.y);
ctx.lineTo(pt2.x,pt2.y);
ctx.stroke();
}
});
</script>
</body>
</html>

Related

Correctly Increasing The Size Of A Video Camera Without Ruining The Aspect Ratio

I have a web page that displays a video where the user can see them self with the computer's camera.
The issue is the camera is too small and when I make the height and width 400px, the aspect ratio is ruined.
Not only this, but the top camera output fill the entire border.
The following is an image showing this happening:
top-camera
The following is the facial-login.html file:
<!DOCTYPE html>
<html>
<head>
<style>
#video {
border: 1px solid black;
width: 320px;
height: 240px;
}
#photo {
border: 1px solid black;
width: 320px;
height: 240px;
}
#canvas {
display: none;
}
.camera {
width: 320px;
display: inline-block;
}
.output {
width: 320px;
display: inline-block;
}
#startbutton {
display: block;
position: relative;
margin-left: auto;
margin-right: auto;
bottom: 36px;
padding: 5px;
background-color: #6a67ce;
border: 1px solid rgba(255, 255, 255, 0.7);
font-size: 14px;
color: rgba(255, 255, 255, 1.0);
cursor: pointer;
}
.contentarea {
font-size: 16px;
font-family: Arial;
text-align: center;
}
/* .sendButton {
background-color: #4CAF50;
border: none;
color: white;
padding: 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 12px;
} */
.sendButton {
position: absolute;
top: 327px;
text-align: center;
}
</style>
<!--The title of the HTML document.-->
<title>Facial Image Recognition</title>
</head>
<body>
<div class="contentarea">
<h1 align="center">Facial Image Recognition</h1>
<div class="camera">
<video id="video">Video stream not available.</video>
</div>
<!--An id on a <button> tag assigns an identifier to the button.
The id allows JavaScript to easily access the <button> element
and manipulate it.-->
<button id="startbutton">Capture Image</button>
<!--The following button will trigger the JavaScript function.-->
<!-- <button class="sendButton">Submit Facial Image</button> -->
<button class="sendButton">Submit Facial Image</button>
<!--The HTML canvas tag is where the image frames are stored
before they are converted into an image of proper format
to be shown using the <img> tag.-->
<canvas id="canvas"></canvas>
<div class="output">
<img id="photo" alt="The image captured will appear in this box.">
</div>
</div>
<script>
var data;
(function() {
// We will scale the photo width to this.
var width = 400;
// The height will be computed based on the input stream.
var height = 0;
var streaming = false;
var video = null;
var canvas = null;
var photo = null;
var startbutton = null;
function startup() {
video = document.getElementById('video');
canvas = document.getElementById('canvas');
photo = document.getElementById('photo');
/*The following line is executed when a user clicks on the
"Capture Image" button.
document.getElementById returns the element whose 'id'
is 'startbutton'.*/
startbutton = document.getElementById('startbutton');
// Access the video stream from the webcam.
navigator.mediaDevices.getUserMedia({
video: true,
audio: false
})
// Upon success, stream video in a video tag.
.then(function(stream) {
video.srcObject = stream;
video.play();
})
.catch(function(err) {
console.log("An error occurred: " + err);
});
video.addEventListener('canplay', function(ev) {
if (!streaming) {
height = video.videoHeight / (video.videoWidth / width);
if (isNaN(height)) {
height = width / (4 / 3);
}
video.setAttribute('width', width);
video.setAttribute('height', height);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
streaming = true;
}
}, false);
startbutton.addEventListener('click', function(ev) {
takepicture();
ev.preventDefault();
}, false);
clearphoto();
}
/*Collect the frames of the photo from the canvas and then
convert it into a PNG format, so that it can be shown in
the HTML page.*/
function clearphoto() {
var context = canvas.getContext('2d');
context.fillStyle = "#AAA";
context.fillRect(0, 0, canvas.width, canvas.height);
var data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);
}
/*Capture a frame from the video stream.*/
function takepicture() {
var context = canvas.getContext('2d');
if (width && height) {
canvas.width = width;
canvas.height = height;
/*The canvas takes a snapshot of the video.*/
context.drawImage(video, 0, 0, width, height);
/*toDataURL('image/png') returns a data URL containing a
representation of the image in PNG format.
'data' will hold the URL link of each image that is
captured from the camera.*/
data = canvas.toDataURL('image/png');
/*'src' is the name of the attribute whose value is to be set.
'data' is a string containing the value to assign to the attribute.
The data is fed as a source of the image element.*/
photo.setAttribute('src', data);
let facialImageURL = '<img src="'+data+'"/>';
// document.write('<img src="'+data+'"/>');
}else {
clearphoto();
}
}
/*The following code will call the startup() function when
the HTML page is loaded.*/
window.addEventListener('load', startup, false);
})();
var URL = "{% url 'facial-login-result' %}";
/*POST the data (the facial image) to the server via AJAX.*/
function SendFacialImage(){
var facialImage = {'data': data};
$.post(URL, facialImage, function(response){
if(response === 'success')
{
alert('Facial Image Successfully Sent!');
}
else{
alert('Error Sending Facial Image!');
}
});
}
$(document).ready(function(){
$('#sendButton').click(function(){
SendFacialImage();
});
});
</script>
</body>
</html>

How can I position the element at very precise pixel on image using Top and Left CSS property

I want to display a dot at specific pixel on image click. I'm displaying it by giving top and left values in %. What happening is the dot isn't moving when clicked another pixel present inside the dot.
When click outside then it is moving. I don't understand why this is happening.
May be it is because there is very small change in top and left values for each pixel.
I've updated CSS for displaying dot within the circle
.hObiiS{
border: solid 1px #303030 !important;
background: rgba(0, 0, 0, 0.3);
border-radius: 50%;
box-sizing: border-box;
box-shadow: none !important;
height: 9px !important;
position: absolute;
transform: translate3d(-50%, -50%, 0);
width: 9px !important;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.hObiiS::before{
position: absolute;
content: '';
width: 1px;
height: 1px;
background-color: rgb(224, 1, 1);
border-radius: 50%;
}
<div class="hObiiS" style="top: 25.4601%; left: 58.6382%;"></div>
Can someone please provide solution to move dot per pixel ?
Here is your problem solution.
let container = document.querySelector('img');
let dot = document.getElementById('dot');
document. addEventListener('click', function( e ) {
if (container === event.target && container.contains(e. target)) {
var parentPosition = getPosition(container);
var xPosition = e.clientX - parentPosition.x - (dot.clientWidth / 2);
var yPosition = e.clientY - parentPosition.y - (dot.clientHeight / 2);
dot.style.left = xPosition + "px";
dot.style.top = yPosition + "px";
}
});
// Helper function to get an element's exact position
function getPosition(el) {
var xPos = 0;
var yPos = 0;
while (el) {
if (el.tagName == "BODY") {
// deal with browser quirks with body/window/document and page scroll
var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
var yScroll = el.scrollTop || document.documentElement.scrollTop;
xPos += (el.offsetLeft - xScroll + el.clientLeft);
yPos += (el.offsetTop - yScroll + el.clientTop);
} else {
// for all other non-BODY elements
xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPos += (el.offsetTop - el.scrollTop + el.clientTop);
}
el = el.offsetParent;
}
return {
x: xPos,
y: yPos
};
}
.container {
position: relative;
cursor: "crosshair";
}
#dot {
position: absolute;
top: 0;
left: 0;
width: 10px;
height: 10px;
display: inline-block;
background-color: red;
transform: translate(100, 0);
}
<!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>Document</title>
</head>
<body>
<div class="container">
<img width="200px" alt="" src="https://img.rawpixel.com/s3fs-private/rawpixel_images/website_content/upwk62143495-wikimedia-image.jpg?w=800&dpr=1&fit=default&crop=default&q=65&vib=3&con=3&usm=15&bg=F4F4F3&ixlib=js-2.2.1&s=218f80fbd029cd0fa69b8597ef4928c0" />
<span id="dot" />
</div>
</body>
</html>
Codepen
Your mouse click position (e.clientX and e.clientY) is relative to your browser's top-left corner that's why your click position is not accurate. You can study the details explanation in this article.
Move Element to Click Position
You need to stop the dot from stopping the click going through to the image.
You can use pointer-events for that.
Here's a simple example:
.container {
position relative;
display: inline-block;
width: 30vmin;
height: 30vmin;
}
img {
position: relative;
width: 100%;
height: 100%;
object-fit: cover;
}
.dot {
background: red;
width: 30px;
height: 30px;
border-radius: 50%;
position: absolute;
top: 10%;
left: 10%;
pointer-events: none;
}
<div class="container"><img onclick="alert('I saw the click');" src="https://picsum.photos/id/1015/300/300">
<div class="dot"></div>
</div>

babylon.js scene with transparent background won't show image/ text behind it z-index

i want to show text behind a babylon.js scene. I've made the background transparent but i can't see the text behind it. I've also tried z-index:-1 for the text.
I've only been learning Babylon since last night so I'm really not too sure whats going on. I'm also not good at java Script so any help would be greatly appreciated :)
\\\\\<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BBY TIAL </title>
<script src="https://cdn.babylonjs.com/babylon.max.js"></script>
<style>
*{
background-color: pink;
}
#canvas {
width:80%;
height:80vh;
z-index:10;
border:0;
padding:0;
margin:0;
background-color: transparent;
}
#maya{
font-size: 300px;
color:white;
position: absolute;;
background-color: transparent;
z-index:-200;
}
#wright{
font-size: 300px;
color:white;
position: fixed;
z-index:1;
top:50vh;
left:40%;
background-color: transparent;
}
#full{
z-index: -9;
}
</style>
</head>
<body>
<h1 id="maya">MAYA</h1>
<h2 id="wright">WRIGHT</h2>
<canvas id="canvas"></canvas>
<script>
window.addEventListener('DOMContentLoaded', function(){
var canvas = document.getElementById('canvas');
var engine = new BABYLON.Engine(canvas, true,);
engine.enableOfflineSupport = false; // Dont require a manifest file
var createScene = function(){
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color4(0, 0, 0, 0);
var camera = new BABYLON.ArcRotateCamera("arcCam",
BABYLON.Tools.ToRadians(0),
BABYLON.Tools.ToRadians(0),
7.,BABYLON.Vector3.Zero(),scene);
camera.attachControl(canvas,true);
var light = new BABYLON.PointLight("PointLight",new BABYLON.Vector3(
5,5,5),scene);
light.parent = camera;
light.intensity = 1000.5;
BABYLON.SceneLoader.ImportMesh("","","ShippingContainer.babylon",
scene,function(newMeshes) {
newMeshes.forEach(function(mesh){
mesh.rotation = new BABYLON.Vector3(BABYLON.Tools.ToRadians(
0),0,0);
} );
});
return scene;
}
var scene = createScene();
engine.runRenderLoop(function(){
scene.render();
});
});
</script>
<h1 id="full">Maya<br/>Wright</h1>
<style>
#canvas{
background: transparent;
}
h1{
background-color: transparent;
font-size: large;
top:5vh;
left:40%;
position: absolute;
}
</style>
</body>
</html>
\\
The main issue here is setting background color to '*' elements, which prevents the image to be shown. When removing it (and adding it only to body), the h1s (with the negative z index) are shown behind the babylon scene:
Note that I didn't use your model, but the default babylon scene, as i have no access to it.
There is no need to set the canvas' background color to be transparent, the scene.clearColor parameter is doing it for you.

generate writing in individual circles in html

I am trying to write a basic html file, which is essentially one page with a bunch of information. I've written the html file but am now trying to improve its appearance. For the heading of the page I have:
<html>
<body>
<center>
<h1> my web </h1>
</center>
</body>
</html>
which is basically the name of the website.
Next, I am trying to alter the heading so that each letter is in an individual circle:
I can produce an individual circle with:
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'purple';
context.fill();
</script>
</body>
</html>
But aren't sure of how to go from here to produce the desired outcome.
Any pointers of how to do this would be appreciated.
Here's a start. You could easily add a gradient to get a convex look.
h1 {
display: table-row;
}
h1 .letter {
width: 80px;
height: 80px;
border-radius: 50%;
background-color: purple;
color: white;
display: table-cell;
text-align: center;
vertical-align: middle;
}
h1 .spacer {
width: 1em;
display: table-cell;
}
<h1>
<span class="letter">a</span>
<span class="letter">d</span>
<span class="letter">d</span>
<span class="letter">s</span>
<span class="spacer"></span>
<span class="letter">u</span>
<span class="letter">p</span>
</h1>
Demo

CSS: Is it possible to make an element look like a sine/cosine function?

On my page I want elements that will serve as horizontal "breaks" in the same way as hr elements, but I would like them to be shaped like a sine function.
Is that possible? If so, how?
Here's a fiddle for you to complete: http://jsfiddle.net/pdov7u85/
HTML:
<p>Here's some red text</p>
<!--some element with id someElement will go here-->
<p>Here's some blue text, which should be divided from the red text with a wavy line</p>
CSS:
p:nth-of-type(1)
{
color: red;
}
#someElement
{
}
p:nth-of-type(2)
{
color: blue;
}
Challenge accepted.
.sine {
text-align: center;
}
.sine_span {
display: inline-block;
margin:0;
padding:0;
height: 20px;
width: 40px;
border: 1px solid black;
}
.sine_span_first {
border-bottom: none;
border-radius: 20px 20px 0 0;
transform: translate(-20px, 0) scale(2,1);
}
.sine_span_second {
border-top: none;
border-radius: 0 0 20px 20px;
transform: translate(20px, 20px) scale(2,1);
}
.sine_span_first_2 {
transform: translate(0, 20px) scale(1,2);
}
.sine_span_second_2 {
transform: translate(0, 60px) scale(1,2);
}
Flat curve
<div class="sine">
<span class="sine_span sine_span_first"></span><span class="sine_span sine_span_second"></span>
</div>
<br />
Sharp curve
<div class="sine">
<span class="sine_span sine_span_first sine_span_first_2"></span><span class="sine_span sine_span_second sine_span_second_2"></span>
</div>
Btw, shouldn't you use some gif image for this?
You could draw that sine function in javascript:
var canvas = document.getElementById("canvas");
if (canvas == null || !canvas.getContext) {
return;
}
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "rgb(11,153,11)";
for (var i = 0; i <= 1000; i++) {
var x = i * 5;
var y = Math.sin(5 * x + 1);
ctx.lineTo(0.5 + x, 25 - y * 24);
}
ctx.stroke();
JSFiddle
Or you could just use an SVG image like Paulie_D suggested.
As #Paulie_D said don't over think it.
Be semantic and use a HR, give it a height and a background image.
hr{
border:none;
height:82px;
background:url('http://i60.tinypic.com/df8y75.png');
background-size:50%;
}
eg.
http://jsfiddle.net/pdov7u85/3/
note: background-size is not supported in older versions of IE but I only used it for convenience.