I have a class, which basically draws a 16x30 grid.
Ideally, I would like to be able to execute:
OSD.setCursor(x y);
OSD.print('Text');
and have it position the word Text at position x, y with each character of Text positioned in the correct location in the grid.
Here's what I have so far:
class MAX7456 {
constructor() {
this.items = null;
this.divs = null;
}
begin() {
var ratioH = 16,
ratioW = 30;
var parent = $('<div />', {
class: 'grid',
width: ratioW * 25,
height: ratioH * 18
}).addClass('grid').appendTo('body');
for (var i = 0; i < ratioH; i++) {
for(var p = 0; p < ratioW; p++) {
this.divs = $('<div />', {
width: 25 - 1,
height: 18 - 1
}).appendTo(parent);
this.items = $('<span />', {
width: 25 - 1,
height: 18 - 1,
style: "padding-left: 2px;"
}).appendTo(this.divs);
}
}
}
setCursor(x, y) {
$('div > span:nth-child(2n-1)').text(function (i, txt) {
$(this).append(i)
i++;
//console.log(txt + $(this).next().text());
});
}
print (txt) {
}
}
var OSD = new MAX7456();
OSD.begin(); // create grid
OSD.setCursor(0, 0); // set text at cursor (x, y)
OSD.print("Label 2");
body {
padding: 0;
font-size: 12px;
}
.grid {
border: 1px solid #ccc;
border-width: 1px 0 0 1px;
}
.grid div {
border: 1px solid #ccc;
border-width: 0 1px 1px 0;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
JSFiddle
Now this may seems not the ideal solution looking for, In that case my apologies. My requirement was to create a tiled grid based on an image so this how i managed to do it.
Total tile count can be vary as you need. (My case 2500 tiles)
When you adjust the image size that will determine what size of the tile can be.
(function($) {
var imagePadding = 0;
var pluginName = "tiles",
defaults = {
x: 2, // tiles in x axis
y: 2, // tiles in y axis
gap: {
x: 1,
y: 1
}
};
function Plugin(elem, options) {
options = $.extend({}, defaults, options);
var $elem = $(elem).wrap("<div class='tiles-wrapper' />"),
width = $elem.outerWidth(),
height = $elem.outerHeight(),
n_tiles = options.x * options.y,
tiles = [];
$elem.parent(".tiles-wrapper").css({
position: "relative",
width: width,
height: height
});
for (var $i = 0; $i < n_tiles; $i++) {
if ($i >= imagePadding) {
tiles.push("<div class='tile' data-id='" + $i + "' data-clipboard-text='" + $i + "'>" + $i + "</div>");
} else {
tiles.push("<div class='tile' data-id='" + $i + "' data-clipboard-text='" + $i + "'></div>");
}
}
var $tiles = $(tiles.join(""));
// Hide original image and insert tiles in DOM
$elem.hide().after($tiles);
// Set backgrounds
$tiles.css({
float: "left",
width: (width / options.x) - (options.gap.x || options.gap),
height: (height / options.y) - (options.gap.y || options.gap),
marginRight: options.gap.x || options.gap,
marginBottom: options.gap.y || options.gap,
backgroundImage: "url(" + $elem[0].src + ")",
lineHeight: (height / options.y) - (options.gap.y || options.gap) + "px",
textAlign: "center"
});
// Adjust position
$tiles.each(function() {
var pos = $(this).position();
this.style.backgroundPosition = -pos.left + "px " + -pos.top + "px";
});
}
$.fn[pluginName] = function(options) {
return this.each(function() {
new Plugin(this, options);
});
};
}(jQuery));
window.onload = function() {
$('#img').tiles({
x: 21.909,
y: 21.909
});
$(".tile").click(function() {
console.log($(this).data("id"));
});
};
.tiles-wrapper {
z-index: 999;
}
.tile:hover {
opacity: .80;
filter: alpha(opacity=80);
background: #fecd1f!important;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="container">
<div class="row">
<div class="col-md-8">
<div class="banner-head"></div>
<div class="row">
<div class="col-md-12">
<div class="image-holder">
<img id="img" src="data:image/gif;base64,R0lGODlh6ANsAwAAACH5BAAAAAAALAAAAADoA2wDhwAAAAAAMwAAZgAAmQAAzAAA/wArAAArMwArZgArmQArzAAr/wBVAABVMwBVZgBVmQBVzABV/wCAAACAMwCAZgCAmQCAzACA/wCqAACqMwCqZgCqmQCqzACq/wDVAADVMwDVZgDVmQDVzADV/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMrADMrMzMrZjMrmTMrzDMr/zNVADNVMzNVZjNVmTNVzDNV/zOAADOAMzOAZjOAmTOAzDOA/zOqADOqMzOqZjOqmTOqzDOq/zPVADPVMzPVZjPVmTPVzDPV/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YrAGYrM2YrZmYrmWYrzGYr/2ZVAGZVM2ZVZmZVmWZVzGZV/2aAAGaAM2aAZmaAmWaAzGaA/2aqAGaqM2aqZmaqmWaqzGaq/2bVAGbVM2bVZmbVmWbVzGbV/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kAZpkAmZkAzJkA/5krAJkrM5krZpkrmZkrzJkr/5lVAJlVM5lVZplVmZlVzJlV/5mAAJmAM5mAZpmAmZmAzJmA/5mqAJmqM5mqZpmqmZmqzJmq/5nVAJnVM5nVZpnVmZnVzJnV/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswAmcwAzMwA/8wrAMwrM8wrZswrmcwrzMwr/8xVAMxVM8xVZsxVmcxVzMxV/8yAAMyAM8yAZsyAmcyAzMyA/8yqAMyqM8yqZsyqmcyqzMyq/8zVAMzVM8zVZszVmczVzMzV/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8rAP8rM/8rZv8rmf8rzP8r//9VAP9VM/9VZv9Vmf9VzP9V//+AAP+AM/+AZv+Amf+AzP+A//+qAP+qM/+qZv+qmf+qzP+q///VAP/VM//VZv/Vmf/VzP/V////AP//M///Zv//mf//zP///wAAAAAAAAAAAAAAAAiuAPcJHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuXMGPKnEmzps2bOHPq3Mmzp8+fQIMKHUq0qNGjSJMqXcq0qdOnUKNKnUq1qtWrWLNq3cq1q9evYMOKHUu2rNmzaNOqXcu2rdu3cOPKnUu3rt27ePPq3cu3r9+/gAMLHky4sOHDiBMrXsy4sePHkCNLnky5suXLmDNrSN7MubPnz6BDix5NurTp06hTq17NurXr17Bjy55Nu7bt27hz697Nu7fv38CDCx9OvLjx48iTK1/OvLnz59CjS59Ovbr169izaznfzr279+/gw4sfT768+fPo06tfz769+/fw48ufT7++/fv48+vfz7+///8ABijggAQWaOCBCCao4II0DDbo4IMQRijhhBRWaOGFGGao4YYcdujhhyCGKOKIJJZo4okopqjiiiy26OKLMMYo44w01i1o44045qjjjjz26OOPQAYp5JBEFmnkkUgmqeSSTDbp5JNQRinllFRWaeWVWGYpqeWWXHbp5ZdghinmmGSWaeaZaKap5ppstunmm3DGKeecdNZp55145qkn55589unnn4AGKuighBZq6KGIJqrooow26uijkEYq6aSUVmrppZhmI6rpppx26umnoIYq6qiklmrqqaimquqqrLbq6quwxirrrLTWImrrrbjmquuuvPbq66/ABivssMQWa+yxyCar7LLMNuvss9AfRivttNRWa+212Gar7bbcduvtt+CGK+645JZr7rnoph6r7rrstuvuu/DGK++89NZr77345qvvvvz26++/AAcdLPDABBds8MEIJ6zwwgw37PDDEEcs8cQUV2zxxRgbZ6zxxhx37PHHIIcs8sgkl2zyySinrPLKLLfsG/LLMMcs88w012zzzTjnrPPOPPfs889ABy300BlEF2300UgnrfTSTDft9NNQRy311FRXbfXVGVhnrfXWXHft9ddghy322GSXbfbZaKet9toXbLft9ttwxy333HTXbffdeOet99589+0X99+ABy744IQXbvjhiCeu+OKMN+7445AWRy755JRXbvnlmGeu+eacd+7556CHLhf66KSXbvrpqKeu+uqst+7667DHLvvstBXXbvvtuOeu++689+7778AHL/zwxBcVb/zxyCev/PLMN+/889BHL/301FdvFP312Gev/fbcd+/99+CHL/745JdvFP756Kev/vrst+/++/DHL//89NdvFf/9+Oev//789+///wAMoAAHSMACGhXwgAhMoAIXyMAGOvCBEIygBCdIwQoUWvCCGMygBjfIwQ568IMgDKEIR0gVwhKa8IQoTKEKV8jCFrrwhTCMoQxnE0jDGtrwhjjMoQ53yMMe+vCHQAwVohCHSMQiGvGISEyiEpfIxCY68YlQE4yiFKdIxSpa8YpYzKIWt8jFLnoS8YtgDKMYx0jGMprxjGhMoxrXE8jGNrrxjXCMoxznSMc62vGOeMwSox73yMc++vGPgAykIAdJyEIaE/KQiEykIhfJyEY68pGQjKQkJ0kSyUpa8pKYzKQmN8nJTnryk6AMEaUoR0nKUprylKhMpSpXycpWErrylbCMpSxnScta2vKWuMylLhB3ycte+vKXwAymMIdJzGIaEvOYyEymMpfJzGY685nQjKY0pxFJzWpa85rYzKY2t8nNbnrzmxDgDKc4x0nOcprznOhMpzrXEcnOdrrznfCMpzznSc962vOeEPjMpz73yc9++vOfAA2oQAcPStCCGvSgCE2oQhfK0IY6EfShEI2oRCdK0Ypa9KIYzahGDzfK0Y569KMgDalIR0rSkg+a9KQoTalKV8rSlrr0pTAPjalMZ0rTmtr0pjjNqU53D8rTnvr0p0ANqlCHStSiGg/1qEhNqlKXytSmOvWpUI0PqlSnStWqWvWqWM2qVrfKENWuevWrYA2rWMdK1rKa9awNaE2rWtfK1ra69a1wjQ+rXOdK17ra9a54zate98oO17769a+ADaxgB0vYwhoP9rCITaxiF8vYxjr2sZCNDqxkJ0vZylr2spjNrGY3DsvZznr2s6ANrWhHS9rSDpr2tKhNrWpXy9rWuva1DbCNrWxnS9va2va2uM0OrW53y9ve+va3wA2ucIcOS9ziGve4yE2ucpfL3OYMOve50I2udKdL3epaDve62M2udrfL3e5697vgDg2veMdL3vKa97zoTa96DNfL3va6973wja985wxL3/ra9774za9+98sO3/76978ADrCAB0zgAhsN+MAITrCCF8zgBjv4wQwQjrCEJ0zhClv4whgOzrCGN8zhDnv4wyAOsYgQR0ziEpv4xChOsYpX7JqAAAA7"
alt="event picture" />
</div>
</div>
</div>
</div>
</div>
</div>
Related
I have created three circles and made it bounce off the wall without using HTML canvas. Now I want two circles to collide with each other and move those circles in the opposite direction. I tried to detect the collision by checking it's position but it doesn't work. I don't know where I went wrong.
Here's my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Bounce Ball</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.circle{
height: 50px;
width: 50px;
position: absolute;
border-radius: 50%;
}
.container {
height: 300px;
width: 300px;
background-color: skyblue;
position: relative;
}
</style>
</head>
<body>
<div class ="container" id ="container">
<div class="circle" id = "circle1" style="background-color:black;
height: 50px; width: 50px;top:0; left:0"></div>
<div class="circle" id ="circle2" style="background-color:rgb(197, 100,
100);height: 50px; width: 50px;top:200px;left: 150px"></div>
<div class="circle" id ="circle3" style="background-color:brown;height:
50px;width: 50px;top:50px;left: 640px"></div>
</div>
<script>
var container = document.getElementById("container");
container.style.width="700px";
container.style.height = "300px";
var balls = document.getElementsByClassName("circle");
for(var i=0; i <balls.length; i++){
var speed={x:3,y:-3}
setInterval(draw, 50 , balls[i], speed);
}
function draw(ball, speed) {
if(parseInt(ball.style.left) > (parseInt(container.style.width)-
parseInt(ball.style.width)) || (parseInt(ball.style.left) <0) ){
speed.x = -speed.x;
}
ball.style.left = parseInt(ball.style.left) + speed.x + 'px';
if(parseInt(ball.style.top) > (parseInt(container.style.height)-
parseInt(ball.style.height)) || (parseInt(ball.style.top) <0)){
speed.y = -speed.y;
}
ball.style.top = parseInt(ball.style.top) + speed.y + 'px';
//for colliding two circles
for(var i =0 ; i <= balls.length-1; i++){
for(var j = i + 1; j < balls.length; j++){
if(parseInt(balls[i].style.left) +
parseInt(balls[i].style.width) ==
parseInt(balls[j].style.left) ||
parseInt(balls[j].style.left) +
parseInt(balls[j].style.width) ==
parseInt(balls[i].style.left) &&
parseInt(balls[i].style.top) +
parseInt(balls[i].style.height) ==
parseInt(balls[j].style.top) || parseInt(balls[j].style.top)
+ parseInt(balls[j].style.height) ==
parseInt(balls[i].style.top)) {
speed.x = - speed.x;
speed.y = -speed.y;
}
ball[i].style.left = parseInt(ball[i].style.left) +
speed.x + 'px';
ball[j].style.left = parseInt(ball[j].style.left) +
speed.x + 'px';
ball[i].style.top = parseInt(ball[i].style.top) +
speed.y + 'px';
ball[j].style.top = parseInt(ball[j].style.top) +
speed.y + 'px';
}
}
}
</script>
</body>
</html>
I would recommend moving as much as possible into javascript variables so you don't need to consult the HTML for every parameter.
You had quite the number of typos, among them speed.x = - speed.x; where you meant speed.x = -speed.x; and your code was difficult to read without any comments or helper functions to explain what's going on.
I have fixed your typos and restructured your code in the snippet below. Try checking the developer console, typically by pressing F12, as this will show you code errors with line number and severity rating.
In my snippet below i have tried to move the parameters into JavaScript to show how that would work, while still leaving some on the HTML nodes:
//Basic properties
var width = 700;
var height = 300;
//Get container
var container = document.getElementById("container");
// Set dimensions
container.style.width = width + "px";
container.style.height = height + "px";
//Load balls
var balls = Array.prototype.slice.call(document.getElementsByClassName("circle"))
.map(function(ball) {
return {
HTMLNode: ball,
xPos: parseInt(ball.style.left),
yPos: parseInt(ball.style.top),
xAcc: 3,
yAcc: -3,
size: 50
};
});
//Utility functions
function angleBetween(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
function distanceBetween(x1, y1, x2, y2) {
return Math.abs(y2 - y1) + Math.abs(x2 - x1);
}
//Draw function
function draw() {
//Loop through balls
for (var ballIndex1 = 0; ballIndex1 < balls.length; ballIndex1++) {
var ball1 = balls[ballIndex1];
//Collide with horisontal wall
if (ball1.xPos > width - ball1.size || ball1.xPos < 0) {
ball1.xAcc = -ball1.xAcc;
}
//Collide with vertical wall
if (ball1.yPos > height - ball1.size || ball1.yPos < 0) {
ball1.yAcc = -ball1.yAcc;
}
//Collide with other balls
for (var ballIndex2 = ballIndex1 + 1; ballIndex2 < balls.length; ballIndex2++) {
var ball2 = balls[ballIndex2];
//Test within collision distance
if (distanceBetween(ball1.xPos, ball1.yPos, ball2.xPos, ball2.yPos) > ball1.size) {
continue;
}
//Get angle of collision
var angle = angleBetween(ball1.xPos, ball1.yPos, ball2.xPos, ball2.yPos);
//Apply force to acceleration
ball1.xAcc = -Math.cos(angle) * 3;
ball2.xAcc = -ball1.xAcc;
ball1.yAcc = -Math.sin(angle) * 3;
ball2.yAcc = -ball1.yAcc;
}
//Apply acceleration to position
ball1.yPos += ball1.yAcc;
ball1.xPos += ball1.xAcc;
//Apply to node
ball1.HTMLNode.style.left = ball1.xPos + "px";
ball1.HTMLNode.style.top = ball1.yPos + "px";
}
}
//Start simulation
setInterval(draw, 1000 / 60);
.circle {
position: absolute;
border-radius: 50%;
height: 50px;
width: 50px;
}
.container {
height: 300px;
width: 300px;
background-color: skyblue;
position: relative;
}
<div class="container" id="container">
<div class="circle" id="circle1" style="background-color:black;
top:0; left:0"></div>
<div class="circle" id="circle2" style="background-color:rgb(197, 100,
100);top:200px;left: 150px"></div>
<div class="circle" id="circle3" style="background-color:brown;top:50px;left: 640px"></div>
</div>
My scenario : Container (div) with some objects (div). The objects can be moved inside the container (with the option containment set to parent).
Now i need to move multiple objects at once. To do this i found this useful plugin. Unfortunately this plugin does not handle the property containment, as reported here.
My test on JSFiddle , disable this function
$(".obj").on("drag", function(ev, ui)
To active the multiple drag, click on the objects. I was able to block the drag event.
Problem of my test:
At that point i wouldn't know how to reactivate the drag.
Note
I should probably know the direction of the drag (with start - stop events). But at this point i can't stop the drag.
My solutions
But also the K Scandrett solution is very good. It is very difficult to apply in my particular case, which has been simplified in the example.
Always using this plugin for enable the multiple drag. Each time i select multiple objects and drag them, in the dragstart event i do this (change the property containment of the object, depending on the positions of the selected objects) :
//1024 * 648 is the width of the container
$(obj).unbind("dragstart").bind("dragstart" , function(ev, ui){
var dimObjFirst = {
x : parseInt($(this).css("left")),
y : parseInt($(this).css("top"))
};
if($("blablabla > div.ui-selected").length > 1){
var minLeft = 1024,maxRight = 0,minTop = 648,maxDown = 0;
$("blablabla > div.ui-selected").each(function(){
var elem = $(this);
var dim = {
w : parseInt(elem.css("width")),
h : parseInt(elem.css("height")),
l : parseInt(elem.css("left")),
t : parseInt(elem.css("top")),
};
if(dim.l < minLeft) minLeft = dim.l;
if(dim.l + dim.w > maxRight) maxRight = dim.l + dim.w;
if(dim.t < minTop) minTop = dim.t;
if(dim.t + dim.h > maxDown) maxDown = dim.t + dim.h;
});
var offsetContainer = $(".container").offset();
$(this).draggable( "option" , "containment" , [
(dimObjFirst.x - minLeft) + parseInt(offsetContainer.left),
(dimObjFirst.y - minTop) + parseInt(offsetContainer.top),
(dimObjFirst.x + (1024 - maxRight)) + parseInt(offsetContainer.left),
(dimObjFirst.y) + (648 - maxDown) + parseInt(offsetContainer.top)
]);
}
});
$(obj).unbind("dragstop").on("dragstop", function(ev, ui) {
if($("blablabla > div.ui-selected").length > 1) {
$("blablabla > div.ui-selected").each(function(){
$(this).draggable( "option" , "containment" , "parent" );
});
}
});
And add this line of code this._setContainment(); at the start of the function _mouseDrag of the jQuery UI plugin.
Looks like a fun project so....
I implemented it with a bounding box (similar to Twisty's comment).
I figured the benefit of doing it this way is that it will then constrain all multiple selected objects to the bounds of the container.
The bounding box I've coloured so you can visualise how it works. Of course you'd likely leave it transparent in practice.
Code comments are inline, but happy to answer any questions on the code if you have them.
No plugins were used (just jQuery and jQueryUI).
var disableclick = false;
var boundingBoxTop, boundingBoxBottom, boundingBoxLeft, boundingBoxRight;
var $container = $("#container");
var containerHeight = $container.height();
var containerWidth = $container.width();
var containerTop = $container.offset().top;
var containerLeft = $container.offset().left;
// add the bounding box to the container and make it draggable
var $boundingBox = $("<div id='boundingBox' style='position:absolute;background-color:#fcf5d4'>").prependTo($container);
$boundingBox.draggable({
grid: [10, 10],
containment: "parent",
stop: function( event, ui ) {
disableclick = true; // don't want to toggle selection when dragging
setTimeout(function(e){
disableclick = false;
},200);
},
});
$(".obj").click(function(e) {
if (!disableclick) {
var $objClicked = $(this);
$objClicked.toggleClass("ui-selected");
var $selectedItems = $("#container .ui-selected");
// move any items in bounding box back into container before we re-process them
$boundingBox.find('*').each(function() {
var $this = $(this);
if ($this.parent().is($boundingBox)) {
// adjust its positioning to be relative to the container
$this.css("top", ($this.offset().top - containerTop) + "px");
$this.css("left", ($this.offset().left - containerLeft) + "px");
$container.append($this); // return it to the container
}
});
// reversing co-ords to what might be expected here so that we can scale them back to what they need to be for a bounding box
boundingBoxTop = containerHeight;
boundingBoxBottom = 0;
boundingBoxLeft = containerWidth;
boundingBoxRight = 0;
// find the bounds of the smallest rectangle that will cover all the currently selected objects
$selectedItems.each(function() {
var $this = $(this);
var top = $this.offset().top - containerTop;
var bottom = $this.offset().top - containerTop + $this.height();
var left = $this.offset().left - containerLeft;
var right = $this.offset().left - containerLeft + $this.width();
boundingBoxTop = (top < boundingBoxTop) ? top : boundingBoxTop;
boundingBoxBottom = (bottom > boundingBoxBottom) ? bottom : boundingBoxBottom;
boundingBoxLeft = (left < boundingBoxLeft) ? left : boundingBoxLeft;
boundingBoxRight = (right > boundingBoxRight) ? right : boundingBoxRight;
});
// get the height and width of bounding box
var boundingBoxHeight = boundingBoxBottom -= boundingBoxTop;
var boundingBoxWidth = boundingBoxRight -= boundingBoxLeft;
if (boundingBoxBottom > 0) // will be negative when nothing is selected
{
// update the bounding box with its new position and size
$boundingBox.css("top", boundingBoxTop + "px");
$boundingBox.css("left", boundingBoxLeft + "px");
$boundingBox.css("width", boundingBoxWidth + "px");
$boundingBox.css("height", boundingBoxHeight + "px");
// add each selected item to the bounding box so we can drag the box with them in it
$selectedItems.each(function() {
var $this = $(this);
// correct the item's position to be relative to the bounding box
$this.css("top", ($this.offset().top - containerTop - boundingBoxTop) + "px");
$this.css("left", ($this.offset().left - containerLeft - boundingBoxLeft) + "px");
$boundingBox.append($this); // add item to bounding box
});
}
}
});
#container {
position: absolute;
width: 400px;
height: 150px;
background: #eee;
}
.obj {
position: absolute;
background: #ccc;
}
.ui-selected {
background: #1C90F3;
}
#obj1 {
width: 20px;
height: 20px;
left: 20px;
top: 20px;
}
#obj2 {
width: 20px;
height: 20px;
left: 100px;
top: 20px;
}
#obj3 {
width: 20px;
height: 20px;
left: 20px;
top: 100px;
}
#obj4 {
width: 20px;
height: 20px;
left: 100px;
top: 100px;
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/jquery-3.2.1.min.js" />
<div style="margin-bottom:10px">
Click boxes to select/deselect multiple items.<br/>Drag to move selection.
</div>
<div id="container">
<div class="obj" id="obj1"></div>
<div class="obj" id="obj2"></div>
<div class="obj" id="obj3"></div>
<div class="obj" id="obj4"></div>
</div>
I enhance the answer by using jquery ui Selectable plugin
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Draggable - Default functionality</title>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<style>
#container {
position: absolute;
width: 400px;
height: 150px;
background: #eee;
}
.obj {
position: absolute;
background: #ccc;
}
.ui-selected,
.ui-selecting {
background: #1C90F3;
}
#obj1 {
width: 20px;
height: 20px;
left: 20px;
top: 20px;
}
#obj2 {
width: 20px;
height: 20px;
left: 100px;
top: 20px;
}
#obj3 {
width: 20px;
height: 20px;
left: 20px;
top: 100px;
}
#obj4 {
width: 20px;
height: 20px;
left: 100px;
top: 100px;
}
</style>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
</head>
<body>
<div id="container">
<div class="obj" id="obj1"></div>
<div class="obj" id="obj2"></div>
<div class="obj" id="obj3"></div>
<div class="obj" id="obj4"></div>
</div>
<script type="text/javascript">
var disableclick = false;
var boundingBoxTop, boundingBoxBottom, boundingBoxLeft, boundingBoxRight;
var $container = $("#container");
var containerHeight = $container.height();
var containerWidth = $container.width();
var containerTop = $container.offset().top;
var containerLeft = $container.offset().left;
// add the bounding box to the container and make it draggable
var $boundingBox = $("<div id='boundingBox' style='position:absolute;background-color:#fcf5d4'>").prependTo($container);
$boundingBox.draggable({
grid: [10, 10],
containment: "parent",
stop: function (event, ui) {
disableclick = true; // don't want to toggle selection when dragging
setTimeout(function (e) {
disableclick = false;
}, 200);
},
});
$('.obj').draggable({
grid: [10, 10],
containment: "parent",
stop: function (event, ui) {
disableclick = true; // don't want to toggle selection when dragging
setTimeout(function (e) {
disableclick = false;
}, 200);
},
});
function selectionStarted() {
$boundingBox.find('*').each(function () {
var $this = $(this);
if ($this.parent().is($boundingBox)) {
// adjust its positioning to be relative to the container
$this.css("top", ($this.offset().top - containerTop) + "px");
$this.css("left", ($this.offset().left - containerLeft) + "px");
$this.draggable("enable");
$container.append($this); // return it to the container
}
});
$boundingBox.css("top", "0px");
$boundingBox.css("left", "0px");
$boundingBox.css("width", "0px");
$boundingBox.css("height", "0px");
}
function selectedEnded() {
var $selectedItems = $("#container .ui-selected");
// reversing co-ords to what might be expected here so that we can scale them back to what they need to be for a bounding box
boundingBoxTop = containerHeight;
boundingBoxBottom = 0;
boundingBoxLeft = containerWidth;
boundingBoxRight = 0;
// find the bounds of the smallest rectangle that will cover all the currently selected objects
$selectedItems.each(function () {
var $this = $(this);
var top = $this.offset().top - containerTop;
var bottom = $this.offset().top - containerTop + $this.height();
var left = $this.offset().left - containerLeft;
var right = $this.offset().left - containerLeft + $this.width();
boundingBoxTop = (top < boundingBoxTop) ? top : boundingBoxTop;
boundingBoxBottom = (bottom > boundingBoxBottom) ? bottom : boundingBoxBottom;
boundingBoxLeft = (left < boundingBoxLeft) ? left : boundingBoxLeft;
boundingBoxRight = (right > boundingBoxRight) ? right : boundingBoxRight;
});
// get the height and width of bounding box
var boundingBoxHeight = boundingBoxBottom -= boundingBoxTop;
var boundingBoxWidth = boundingBoxRight -= boundingBoxLeft;
if (boundingBoxBottom > 0) // will be negative when nothing is selected
{
// update the bounding box with its new position and size
$boundingBox.css("top", boundingBoxTop + "px");
$boundingBox.css("left", boundingBoxLeft + "px");
$boundingBox.css("width", boundingBoxWidth + "px");
$boundingBox.css("height", boundingBoxHeight + "px");
// add each selected item to the bounding box so we can drag the box with them in it
$selectedItems.each(function () {
var $this = $(this);
// correct the item's position to be relative to the bounding box
$this.css("top", ($this.offset().top - containerTop - boundingBoxTop) + "px");
$this.css("left", ($this.offset().left - containerLeft - boundingBoxLeft) + "px");
$this.draggable("disable");
$boundingBox.append($this); // add item to bounding box
});
}
}
</script>
<script type="text/javascript">
$("#container").selectable({
start: selectionStarted,
stop: selectedEnded
});
</script>
</body>
</html>
I'm using document.getElementById("").style.top = var; to randomly change the position of an object every time I click on it, but I can only randomly change the position by pixels and not percentage. How do I randomly generate a number with % ?
document.getElementById("randObject").onclick = function () {
var bColor = "#"+((1<<24)*Math.random()|0).toString(16);
var yAxis = Math.random()*100;
var xAxis = Math.random()*100;
document.getElementById("randObject").style.backgroundColor = bColor;
document.getElementById("randObject").style.top = yAxis;
document.getElementById("randObject").style.left = xAxis;
}
document.getElementById("randObject").style.top = yAxis + "%";
document.getElementById("randObject").style.left = xAxis + "%";
I should point out that your color generator is also not valid 1/16 of the time. You need to left-zero-pad the string:
"#" + ("00000" + ((1<<24) * Math.random() | 0).toString(16)).slice(-6);
Another shortcut you can use to save DOM lookup time is to use the this keyword in your click event. All together it looks like:
Lastly, you might consider using .addEventListener('click', function() { ... }) since that is the current standard, though what you're doing works alright if you reeeally want to support IE6.
Let's check out the demo since this looks like a pretty neat script now:
document.getElementById("randObject").addEventListener('click', function() {
var bColor = "#" + ("00000" + ((1<<24) * Math.random() | 0).toString(16)).slice(-6);
var yAxis = Math.random() * 100;
var xAxis = Math.random() * 100;
this.style.backgroundColor = bColor;
this.style.top = yAxis + "%";
this.style.left = xAxis + "%";
});
:root {
/* change this value to update the size of playing field and #randObject */
--size: 50px;
}
html {
position: absolute;
margin: 0 var(--size) var(--size) 0;
padding: 0;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
body {
margin: 0;
padding: 0;
}
#randObject {
position: absolute;
top: 0;
left: 0;
width: var(--size);
height: var(--size);
background-color: #000000;
border-radius: 50%;
cursor: pointer;
transition-property: top, left, background-color;
transition-duration: 0.4s;
}
<div id="randObject"></div>
I added positioning to your code and I was able to make it to move by percentage.
<img id="randObject" width=100 height=100>
<script>
document.getElementById("randObject").onclick = function () {
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var bColor = "#"+((1<<24)*Math.random()|0).toString(16);
var yAxis = Math.random() + '%';
var xAxis = Math.random() + '%';
document.getElementById("randObject").style.backgroundColor = bColor;
document.getElementById("randObject").style.top = yAxis;
document.getElementById("randObject").style.left = xAxis;
document.getElementById("randObject").style.position = 'absolute';
}
</script>
I was trying to make a web page with images, which should provide the exact functionality of other pages on the same site. I could do that, except image enlarging feature on it.
Images should be enlarged on a popped-up box. For that, on the other pages a js file is used. (Attached)
The way I have tried is below. Since the other pages' codes are messy I couldn't grab exact thing to do. Help on this is much appreciated.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
$(window).load(function() {
var productThumbImage = $('.search_holder .product-enlarge-trigger img');
productThumbImage.each(function() {
// Get on screen image
var screenImage = $(this);
// Create new offscreen image to test
var theImage = new Image();
theImage.src = screenImage.attr("src");
// Get accurate measurements from that.
var imageWidth = theImage.width;
var imageHeight = theImage.height;
if (imageWidth > imageHeight) {
$(this).addClass('thumbCheckLandscape');
}
});
});
$(".product-enlarge-trigger img").hover(function() {
alert('aaa');
});
$('body').removeClass();
detectThumbs();
function detectThumbs() {
var productThumbImage = $('.product-enlarge-trigger img');
alert(productThumbImage);
productThumbImage.each(function() {
var thumbCheck = $(this).attr('src');
thumbCheck = thumbCheck.split('/');
thumbCheck = thumbCheck[2];
thumbCheck = thumbCheck.replace("%20", "");;
$(this).parent().addClass(thumbCheck);
});
}
</script>
<script type="text/javascript" src="JS/Enlarge/image.enlarge.js"></script>
<style type="text/css">
.tablet_thumb_landscape.thumbCheckLandscape {
margin-top: 16px;
width: 117px !important;
}
.thumbCheckLandscape {
width: 100% !important;
}
.product-enlarge-trigger img {
width: 7%;
position: static !important;
}
.item_thumb_wrapper {
height: 186px;
-webkit-box-shadow: inset 0px -15px 0px 0px rgba(218, 218, 218, 0.99);
-moz-box-shadow: inset 0px -15px 0px 0px rgba(218, 218, 218, 0.99);
box-shadow: inset 0px -15px 0px 0px rgba(218, 218, 218, 0.99);
padding-bottom: 8px;
border-bottom: 8px solid #c8c7c8;
margin-bottom: 8px;
position: relative;
}
.enlarge_thumb_close {
width: 33px;
height: 33px;
right: -16px;
top: -16px;
position: absolute;
display: block;
background: url(../../../Images/Structure/search_enlarge_close.png)top left no-repeat;
background-size: 100%;
z-index: 1001 !important;
}
</style>
</head>
<body>
<div class="item_thumb_wrapper">
<img src="aa\xxx.jpg" class="resize" width="250" />
</div>
<div class="product-enlarge-trigger">
<img src="aa\xxx.jpg" class="resize" width="250" />
</div>
<div class="box">
<img src="aa\xxx.jpg" class="resize" width="250" />
</div>
</body>
</html>
External js file
// Plugin Definition
$.fn.productEnlarge = function(options) {
var defaults = {
'fadeInSpeed': 300,
'lastRowClass': 'last',
'overlayDiv': 'item-overlay-global',
'enlargeDiv': 'product-scroll-enlarge'
}
// Extend our default options with those provided
var opts = $.extend({}, defaults, options);
var getScrollTop = function() {
var ScrollTop = document.body.scrollTop;
if (ScrollTop == 0) {
if (window.pageYOffset)
ScrollTop = window.pageYOffset;
else
ScrollTop = (document.body.parentElement) ? document.body.parentElement.scrollTop : 0;
}
return ScrollTop;
}
var getViewportHeight = function() {
var viewportheight;
// the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
if (typeof window.innerWidth != 'undefined') {
viewportheight = window.innerHeight
}
// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth !=
'undefined' && document.documentElement.clientWidth != 0) {
viewportheight = document.documentElement.clientHeight
}
// older versions of IE
else {
viewportheight = document.getElementsByTagName('body')[0].clientHeight
}
return viewportheight;
}
/*** sniff the UA of the client and show hidden div's for that device ***/
var ua = navigator.userAgent;
var windowwidth = $(window).width();
var checker = {
android: ua.match(/Android/),
appleiPad: ua.match(/iPad/)
};
if (windowwidth <= 660) {
//if (checker.android){
// do nothing
} // end UA detection
else {
// For every trigger passed bind our events
return this.each(function() {
$this = $(this);
$this.mouseover(function() {
var hover_link = $(this).parent().attr('href');
//var hover_call = $(this).parent().attr('rel');
var hover_call = $(this).attr('rel');
//alert (hover_link);
// Create our overlay div
//$('body').append('<a class="enlarge_thumb_close">Close</a>');
$('body').append('');
$(this).parent().parent().find('.card-link').addClass('cardTitleSelected');
//$(this).parent().parent().find('.card-link').appendTo('.product-scroll-enlarge');
//$('.cardTitleSelected').appendTo('.product-scroll-enlarge');
//$('.cardTitleSelected').show();
var product_target_title = $(this).parent().parent().find('.card-link span');
//$('.product-scroll-enlarge').append('<div class="enlarge_title"><div class="et_text_wrap">'+ product_target_title.html() +'<br><strong>A6</strong> £1.79 / <strong>A4</strong> £2.99 / <strong>A3</strong> £5.99</div></div>');
$('.enlarge_title').hide().remove();
$('.product-scroll-enlarge').append('<div class="enlarge_title"><div class="et_text_wrap">' + product_target_title.html() + '</div></div>');
//alert(product_target_title.html());
$('body').append('<div class="enlarge_thumb_close"></div>');
// Get our targets
var target = $('.' + opts.overlayDiv);
// Set a fallback bind to remove this new target on mouseout
target.mouseout(function() {
$(this).remove();
});
var product_target = $(this).parent().parent().parent().find('.' + opts.enlargeDiv);
if (product_target.length == 0) {
return false;
}
$(target).html(product_target.html()).fadeIn(opts.fadeInSpeed);
// Calculate our positioning
var pos_top = (($(this).offset().top + ($(this).height() / 2)) - (target.height() / 2));
var pos_left = $(this).offset().left + $(this).width() + 25;
var totalwidth = pos_left + target.width() + 25;
// If our image goes beyond our viewport width or has a class of 'last' flip our offset
if ($(this).parent().hasClass(opts.lastRowClass) || totalwidth > document.body.offsetWidth) {
pos_left = ($(this).offset().left - target.width()) - 30;
}
var totalheight = (pos_top - getScrollTop()) + parseInt(target.height());
//var totalheight = ((pos_top - getScrollTop()) + ($(this).height() / 2)) - parseInt(taget.height() / 2);
var windowHeight = getViewportHeight();
// If our image goes beyond our window height
if (totalheight > windowHeight) {
var minusval = parseInt(totalheight) - windowHeight;
pos_top = pos_top - (minusval + 30);
}
// If our image is less than the product height, display below
if (totalheight < target.height()) {
pos_top = getScrollTop() + 50;
}
// Set our positional coordinates
$(target).css('top', pos_top).css('left', pos_left);
setTimeout(function() {
//do something special
var mainimagewidth = $('.item-overlay-global img').width();
$('.enlarge_thumb_close').css('top', pos_top - 16).css('left', pos_left + mainimagewidth - 16);
}, 100);
$('.enlarge_thumb_close').click(function() {
$this.hide().remove();
$('.' + opts.overlayDiv).hide().remove();
$('.enlarge_thumb_close').hide().remove();
});
});
$this.mouseout(function() {
var windowwidth = $(window).width();
var ua = navigator.userAgent;
var checker = {
appleiPad: ua.match(/iPad/)
};
if (windowwidth <= 440 || checker.appleiPad) {
} else {
$('.' + opts.overlayDiv).hide().remove();
$('.enlarge_thumb_close').hide().remove();
$('.enlarge_title').hide().remove();
}
//$('.cardTitleSelected').appendTo('.product-scroll-enlarge');
//$('.cardTitleSelected').hide();
//$('.product-scroll-enlarge .cardTitleSelected').after(''+ $this +' .shortlistSave');
});
$('.enlarge_thumb_close').click(function() {
$('.' + opts.overlayDiv).hide().remove();
$('.enlarge_thumb_close').hide().remove();
$('.enlarge_title').hide().remove();
});
$('.item-overlay-global').click(function() {
window.location = hover_link;
});
});
}
};
I am trying to make the smile.png image to appear in a random position within the specific <div>.
What I have done is to set the variable.style.top= top_position+'px' & variable.style.left = left_position+"px".
However, what I am getting so far are the images the are horizontally aligned and not randomly positioned. How am I able to do that?
var theLeftSide = document.getElementById("leftSide");
var randomY = Math.round(Math.random()) + 'px';
var randomX = Math.round(Math.random()) + 'px';
function generateFaces() {
for (numberOfFaces = 0; numberOfFaces < 5; numberOfFaces++) {
createElement(numberOfFaces);
}
}
number = 0;
function createElement() {
number++;
//creating the image on the leftside
var smiley = document.createElement('img');
smiley.src = "smile.png";
smiley.style.position = "absolute";
smiley.style.left = randomX;
smiley.style.top = randomY;
theLeftSide.appendChild(smiley);
}
#leftSide {
position: absolute;
width: 500px;
height: 500px;
}
#rightSide {
position: absolute;
width: 500px;
height: 500px;
left: 500px;
border-left: 1px solid black;
}
<body id="smileyGuessingGame" onload="generateFaces()">
<h1>Matching Game</h1>
<p>Click on the extra smiling face on the left</p>
<div id="leftSide">
</div>
<div id="rightSide">
</div>
</body>
There are few syntax errors in your code. You can compare your code with the code provided below.
Also note toFixed returns a A string representation of numObj that does not use exponential notation and has exactly digits digits after the decimal place.
Try this:
var theLeftSide = document.getElementById("leftSide"),
top_position = parseInt(Math.random() * ($(document).width() - 500)),
left_position = parseInt(Math.random() * ($(document).width() - 500));
function generateFaces() {
for (var numberOfFaces = 0; numberOfFaces < 5; numberOfFaces++) {
createElement(numberOfFaces);
}
}
var number = 0;
function createElement() {
number++;
//creating the image on the leftside
var smiley = document.createElement('img');
smiley.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Smiley_head_happy.svg/2000px-Smiley_head_happy.svg.png";
smiley.style.position = 'absolute';
smiley.style.top = top_position + "px";
smiley.style.left = left_position + "px";
theLeftSide.appendChild(smiley);
top_position += 20;
left_position += 20;
}
#leftSide {
position: absolute;
width: 500px;
height: 500px;
}
#rightSide {
position: absolute;
width: 500px;
height: 500px;
left: 500px;
border-left: 1px solid black;
}
img {
width: 100px;
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<body id="smileyGuessingGame" onload="generateFaces()">
<h1>Matching Game</h1>
<p>Click on the extra smiling face on the left</p>
<div id="leftSide">
</div>
<div id="rightSide">
</div>
</body>
Fiddle here
I'd code this using jQuery and lodash. Here's a jsfiddle:
https://jsfiddle.net/mckinleymedia/3z6wsnyf/2/
The html:
<h1>Matching Game</h1>
<p>Find the unique image</p>
<div class="game"></div>
And the code:
var game = function(options) {
var panes = 2,
game = $('.game'),
height = 500,
width = game.width() / panes - 20,
itemSize = 50,
faces = 5,
guesses = 5,
setupBoard = function() {
game
.empty();
_.times(panes, function(p) {
game
.append(
$('<div>')
.addClass('pane pane' + p)
.css('height', height + 'px')
.css('width', width + 'px')
);
})
},
startGame = function() {
_.times(faces, function(i) {
_.times(panes, function(p) {
$('.pane' + p)
.append(
$('<img>')
.attr('src', 'http://lorempixel.com/200/20' + i)
.addClass('img-' + i)
.css('top', _.random(height - itemSize) + 'px')
.css('left', _.random(width - itemSize) + 'px')
);
})
});
$('.game img').click(function() {
guesses--;
alert('Nope! You\'ve got ' + guesses + ' guesses remaining.');
});
$('.pane' + _.random(panes - 1))
.append(
$('<img>')
.attr('src', 'http://lorempixel.com/200/20'+ (faces + 1))
.addClass('img-t')
.css('top', _.random(height - itemSize) + 'px')
.css('left', _.random(width - itemSize) + 'px')
.click(function() {
alert('You got it! Good job! You just cleared ' + faces + ' images! You\'ve got ' + guesses + ' guesses remaining.');
faces++;
setupBoard();
startGame();
})
);
$('.game img')
.css('height', itemSize + 'px')
.css('width', itemSize + 'px')
.css('-moz-border-radius', itemSize / 2 + 'px')
.css('-webkit-border-radius', itemSize / 2 + 'px')
.css('border-radius', itemSize / 2 + 'px')
.css('-khtml-border-radius', itemSize / 2 + 'px')
};
setupBoard();
startGame();
};
game();
Maybe something like this could work:
function generateRandom(min, max) {
var num = Math.random() * (max - min) + min;
return Math.floor(num);
}
var width,
height,
img;
width = $( '#leftSide' ).width();
height = $( '#leftSide' ).height();
img = $('<img id="smiley">');
img.attr('src', 'http://vignette2.wikia.nocookie.net/robocraft/images/2/26/Smile.png');
img.css('top',generateRandom(0,height));
img.css('left',generateRandom(0,width));
img.appendTo('#leftSide');
demo: http://codepen.io/anon/pen/PZZrzz