how to check whether crop div covers rotated image? - javascript

I want to check whether cropping div covers images in it.Everything works fine when image is not rotated but after rotating image crop does not shows error msg...
Here is fiddle : Fiddle
function isCropValid(){
var $selector = $("#resizeDiv"); // cropping Div
var $img = $("#rotateDiv"); // image div
var $selectorW = $selector.width();
var $selectorH = $selector.height();
var $selectorX = $selector.offset().left ;
var $selectorY = $selector.offset().top ;
var $imgW = $img.width();
var $imgH = $img.height();
var $imgX = $img.offset().left;
var $imgY = $img.offset().top;
var diff_X = $selectorX - $imgX;
var diff_Y = $selectorY - $imgY;
if(diff_X+$selectorW > $imgW){
return false;
} else if(diff_Y+$selectorH > $imgH){
return false;
} else if($selectorX<$imgX){
return false;
} else if($selectorY<$imgY){
return false;
}
else {
return true;
}
}
or another function
function isCropValid(){
var el1 = document.getElementById("resizeDiv"); // cropDiv
var el2 = document.getElementById("rotateDiv"); // imageDiv
var cropdiv = el1.getBoundingClientRect();
var imgdiv = el2.getBoundingClientRect();
return (
((imgdiv.top <= cropdiv.top) && (cropdiv.top <= imgdiv.bottom)) &&
((imgdiv.top <= cropdiv.bottom) && (cropdiv.bottom <= imgdiv.bottom)) &&
((imgdiv.left <= cropdiv.left) && (cropdiv.left <= imgdiv.right)) &&
((imgdiv.left <= cropdiv.right) && (cropdiv.right <= imgdiv.right))
);
}
I above code i have one image inside div.if crop div gets out of this div i m showing label bg color red meaning crop is not correct otherwise i m showing label color green means crop is correct..

I think what you'll have to do is to calculate the positions of each of the 4 points of the image top-left top-right bottom-right and bottom-left, then do the same thing for the crop div something like this:
var $topLeftX=$selectorX-($selectorW/2)-($selectorH/2);
var $topLeftY=$selectorY-($selectorH/2)-($selectorW/2);
var $bottomLeftX=$selectorX-($selectorW/2)+($selectorH/2);
var $bottomLeftY=$selectorY+($selectorH/2)-($selectorW/2);
var $topRightX=$selectorX+($selectorW/2)-($selectorH/2);
var $topRightY=$selectorY-($selectorH/2)+($selectorW/2);
var $bottomRightX=$selectorX+($selectorW/2)+($selectorH/2);
var $bottomRightY=$selectorY+($selectorH/2)+($selectorW/2);
Then compare the corner points.
now the issue is with the corners of the image, as after rotation this will need some sine/cosine calculations.
you might want to take a look at this post: Find the coordinates of the corners of a rotated object in fabricjs
I think it will make your life much easier

So this is gonna be a big hack, but hey :-) The idea is to put the cut out behind the image, and then see whether the image overlaps the cut out on all four corners.
function cutoutIsOK() {
// Grab the cutout element and position it behind the image
var cutout = document.querySelector('#resizeDiv');
cutout.style.zIndex = -1;
// Grab the image
var image = document.querySelector('#rotateDiv img');
// Take the four corners of the cutout element
var cutoutRect = cutout.getBoundingClientRect();
var pos = [
[cutoutRect.left, cutoutRect.top],
[cutoutRect.right - 1, cutoutRect.top],
[cutoutRect.left, cutoutRect.bottom - 1],
[cutoutRect.right - 1, cutoutRect.bottom - 1]
];
// And verify that the image overlaps all four corners
var ok = pos.every(function(p) {
return document.elementFromPoint(p[0], p[1]) === image;
});
// Reset the cutout's z-index to make it visible again
cutout.style.zIndex = 0;
return ok;
}

Related

InDesign script, resize images after word import

Sometimes we have big images in word file and after importing this word file inside InDesign, the image goes inside the overflow text and the text flow stops at this point.
We couldn't resize these images or can't get hold of this image for applying any scripting logic.
Basically, I will search for figure parastyle, then check for rectangles inside the para, and do resize logic. Sample jsx code here:
app.findTextPreferences.appliedParagraphStyle= 'figure';
var founds = app.findText();
// find 92% text width area
var pageWidth = this.props.textAreaWidth * 92 /100;
for(var i=0, len=founds.length; i<len; i++){
// find the rectangles inside the para
var rect = founds[i].rectangles;
if(rect.length == 0) continue;
var vb = rect[0].visibleBounds;
var imgWidth = vb[3] - vb[1];
// image resize logic
if(imgWidth > pageWidth){
vb[3] = pageWidth;
rect[0].visibleBounds = vb;
rect[0].fit(FitOptions.PROPORTIONALLY);
rect[0].fit(FitOptions.FRAME_TO_CONTENT);
}
How to apply some logic to the images which are in the overflow text? how to resize the image which is in overflow text?
We can just import the below word file into any InDesign template
Sample word file
You could iterate through all the graphics and resize the big ones.
var images = app.activeDocument.allGraphics;
var max = {};
max.w = 100; // max width
max.h = 100; // max height
for (var i=0; i<images.length; i++) {
var gb = images[i].geometricBounds;
var size = {};
size.w = -gb[1] + gb[3];
size.h = -gb[0] + gb[2];
if (size.w > max.w || size.h > max.h) {
var scale = (size.w > size.h) ? max.w/size.w : max.h/size.h;
images[i].horizontalScale *= scale;
images[i].verticalScale *= scale;
images[i].parent.fit(FitOptions.FRAME_TO_CONTENT);
}
}

error with arrays in javascript

To fully understand this note this; `when the page loads it gets the area of the image (width * height) and creates all the x,y positions for all the positions in the area.
This works fine.
When I have another area from pos x,y and with also an area (width * height) should pop the positions from the first list so it can separate the two areas.
Little bug I noticed is I get little lines that are horizontal to the selected area and they don't extend far from that. I believe the reason is instead of making a clean square inside the image every line is offseted by a pixel or two.
Here's a video of the behaviour https://youtu.be/v1b6dEmfxQw
so since there's already an all positions list this code created a clone of the array and removes the positions.
var drop_boxes = $('.drop-box');
var area_grid = [];
var image_width = $('.img-class')[0].naturalWidth;
var image_height = $('.img-class')[0].naturalHeight;
drop_boxes.each(function() {
var position = $(this).position();
var width = $(this).width();
var height = $(this).height();
var positions_clone = positions.slice(0);
//console.log(positions_clone.length);
var top_offset = parseInt((position['top'] * image_width)/img_width);
var left_offset = parseInt((position['left'] * image_height)/img_height);
position['top'] = top_offset;
position['left'] = left_offset;
var width_offset = parseInt((width * image_width)/img_width);
var height_offset = parseInt((height * image_height)/img_height);
var width_counter = 0;
var height_counter = 0;
var area = width_offset * height_offset;
console.log(position);
console.log(width_offset);
console.log(height_offset);
if (position['top'] < image_height-1 && position['left'] < image_width) {
for (counter = 0; counter < area; counter++) {
var pos = [parseInt(position['left']+width_counter), parseInt(position['top']+height_counter)];
var index = positions.findIndex(function(item) {
// return result of comparing `data` with `item`
// This simple implementation assumes that all `item`s will be Arrays.
return pos.length === item.length && item.every(function(n, i) { return n === pos[i] });
});
//console.log(pos);
if (index > -1) {
positions_clone.splice(index, 1);
}
//area_grid.push(pos);
if (width_counter == width_offset) {
width_counter = 0;
height_counter += 1;
}
if (counter%100 == 0) {
var percentage = Math.round((counter/area)*100, 2);
console.log("Percentage: "+percentage+"%" + " "+counter);
}
width_counter += 1;
}
console.log(positions_clone.length);
console.log(area_grid.length);
areas[area_counter] = {'area': area_grid, 'positions': positions_clone};
parent.find('.area').text(area_counter);
area_counter += 1;
}
any clues in fixing it will be appreciated. I've showed how it behaves after commenting out certain parts of the code in the video.
Change
var index = positions.findIndex(function(item) {
to
var index = positions_clone.findIndex(function(item) {
Because after each splice, the indices of the original positions doesn't change but you are still using those indices to splice the clone.

How to add a 16x16 grid of pseudo-random tiles as a background in canvas (or other web language)

I have recently been working on a web based project using canvas on HTML5. The program consists of a 16x16 grid of tiles that have been pseudo-randomly generated. I am relatively new to canvas, but have built this program in several other environments, none of which however compile successfully to a web based language. this is the main code section that is giving me bother:
var A = 8765432352450986;
var B = 8765432352450986;
var M = 2576436549074795;
var X = 1;
var rx = 0;
var ry = 0;
this.image = new Image();
var i = 0;
var ii = 0;
while(i < 16)
{
while(ii < 16)
{
this.image = new Image();
this.image.src = "textures/grass.png";
x = (((A*X)+B)%M)%M;
if((x/2)%1 == 0)
{
this.image.src = "textures/grass.png";
}
if((x/8)%1 == 0)
{
this.image.src = "textures/hill.png";
}
if((x/21)%1 == 0)
{
this.image.src = "textures/trees.png";
}
if((x/24)%1 == 0)
{
this.image.src = "textures/sea.png";
}
if((x/55)%1 == 0)
{
this.image.src = "textures/mountain.png";
}
if((x/78)%1 == 0)
{
this.image.src = "textures/lake.png";
}
if((x/521)%1 == 0)
{
this.image.src = "textures/volcano.png";
}
if((x/1700)%1 == 0)
{
this.image.src = "textures/shrine.png";
}
if((x/1890)%1 == 0)
{
this.image.src = "textures/outpost.png";
}
if((x/1999)%1 == 0)
{
this.image.src = "textures/civ.png";
}
ctx = myGameArea.context;
ctx.drawImage(this.image,rx, ry, 20, 20);
ii ++;
rx += 20;
}
i ++;
rx = 0;
ry += 16;
}
I would like canvas to draw along the lines of this code above, effectively generating a grid like this
pre generated grid image
(please try and ignore the obvious bad tile drawings, I planned on either finding an artist or trying slightly harder on them when I get the game fully working.)
The black square is a separate movable object. I haven't got as far as implementing it in this version, but if you have any suggestions for it please tell me
in the full html file I have now, the canvas renders but none of the background (using the w3schools tutorials, I can make objects render however)
In short: how do I render a background consisting of a 16x16 grid of pseudo-random tiles on an event triggered or on page loaded, using canvas or if that does not work another web based technology
Thank you for your time.
A few problems but the main one is that you need to give an image some time to load before you can draw it to the canvas.
var image = new Image();
image.src = "image.png";
// at this line the image may or may not have loaded.
// If not loaded you can not draw it
To ensure an image has loaded you can add a onload event handler to the image
var image = new Image();
image.src = "image.png";
image.onload = function(){ ctx.drawImage(image,0,0); }
The onload function will be called after all the current code has run.
To load many images you want to know when all have loaded. One way to do this is to count the number of images you are loading, and then use the onload to count the number of images that have loaded. When the loaded count is the same as the loading count you know all have loaded and can then call a function to draw what you want with the images.
// Array of image names
const imageNames = "grass,hill,trees,sea,mountain,lake,volcano,shrine,outpost,civ".split(",");
const images = []; // array of images
const namedImages = {}; // object with named images
// counts of loaded and waiting toload images
var loadedCount = 0;
var imageCount = 0;
// tile sizes
const tileWidth = 20;
const tileHeight = 20;
// NOT SURE WHERE YOU GOT THIS FROM so have left it as you had in your code
// Would normally be from a canvas element via canvasElement.getContext("2d")
var ctx = myGameArea.context;
// seeded random function encapsulated in a singleton
// You can set the seed by passing it as an argument rand(seed) or
// just get the next random by not passing the argument. rand()
const rand = (function(){
const A = 8765432352450986;
const B = 8765432352450986; // This value should not be the same as A?? left as is so you get the same values
const M = 2576436549074795;
var seed = 1;
return (x = seed) => seed = ((A * x) + B) % M;
}());
// function loads an image with name
function addImage(name){
const image = new Image;
image.src = "textures/" + name + ".png";
image.onload = () => {
loadedCount += 1;
if(loadedCount === imageCount){
if(typeof allImagesLoaded === "function"){
allImagesLoaded();
}
}
}
imageCount += 1;
images.push(image);
namedImages[name] = image;
}
imageNames.forEach(addImage); // start loading all the images
// This function draws the tiles
function allImagesLoaded(){ /// function that is called when all the images have been loaded
var i, x, y, image;
for(i = 0; i < 256; i += 1){ // loop 16 by 16 times
ctx.drawImage(
images[Math.floor(rand()) % images.length]; //random function does not guarantee an integer so must floor
(i % 16) * tileWidth, // x position
Math.floor(i / 16) * tileHeight, // y position
tileWidth, tileHeight // width and height
);
}
}

How to dynamically shift a DIV down based on predecessor

I've got a series of DIVs, all with the same class (.ms-acal-item). What I'm trying to do is get the position of each one, compare it to the one above it, and shift it down if needed. This is to correct an issue on a SharePoint 2013 calendar where event tiles are overlapping. Here's my code so far:
$(function() {
$('.ms-acal-item').each(function(i, obj) {
var tile = jQuery(this);
var prev = tile.prev();
var prevPos = prev.position();
var tilePOs = tile.position();
var curTop = parseInt(tilePos.top);
var newTop = parseInt(prevPos.top) + 30;
if(curtop !== newTop){
tile.css('top', newTop);
}
});
});
And here's an example of what the SharePoint-generated content looks like:
Each tile is 20px high and positioned absolutely in-line. What I need to do is compare the position of each tile to its predecessor and then move it down 30px if it isn't already there (20px for the tile and 10px between them). So far it's not working - my code seems to have no effect on the tile positions.
What am I doing wrong?
There is a problem in the logic, while processing the first element we do not have any previous element, so we need to ignore it and few typo(variable case issues) mistakes in your code. Below is the revamp code.(To see the changes effect i changed style from top to margin-left, correct it afterwards)
$(function() {
$('.ms-acal-item').each(function(i, obj) {
var tile = $(this);
var prev = tile.prev();
if (typeof prev.position() !== "undefined") {
var prevPos = JSON.parse(JSON.stringify(prev.position()));
var tilePos = JSON.parse(JSON.stringify(tile.position()));
var curTop = parseInt(tilePos.top);
var newTop = parseInt(prevPos.top) + 30;
if(curTop !== newTop){
tile.css('margin-left', newTop);
}
}
});
});

SVG Camera Pan - Translate keeps resetting to 0 evertime?

Well i have this SVG canvas element, i've got to the point so far that once a user clicks and drags the canvas is moved about and off-screen elements become on screen etc....
However i have this is issue in which when ever the user then goes and click and drags again then the translate co-ords reset to 0, which makes the canvas jump back to 0,0.
Here is the code that i've Got for those of you whio don't wanna use JS fiddle
Here is the JSfiddle demo - https://jsfiddle.net/2cu2jvbp/2/
edit: Got the solution - here is a JSfiddle DEMO https://jsfiddle.net/hsqnzh5w/
Any and all sugesstion will really help.
var states = '', stateOrigin;
var root = document.getElementById("svgCanvas");
var viewport = root.getElementById("viewport");
var storeCo =[];
function setAttributes(element, attribute)
{
for(var n in attribute) //rool through all attributes that have been created.
{
element.setAttributeNS(null, n, attribute[n]);
}
}
function setupEventHandlers() //self explanatory;
{
setAttributes(root, {
"onmousedown": "mouseDown(evt)", //do function
"onmouseup": "mouseUp(evt)",
"onmousemove": "mouseMove(evt)",
});
}
setupEventHandlers();
function setTranslate(element, x,y,scale) {
var m = "translate(" + x + "," + y+")"+ "scale"+"("+scale+")";
element.setAttribute("transform", m);
}
function getMousePoint(evt) { //this creates an SVG point object with the co-ords of where the mouse has been clicked.
var points = root.createSVGPoint();
points.x = evt.clientX;
points.Y = evt.clientY;
return points;
}
function mouseDown(evt)
{
var value;
if(evt.target == root || viewport)
{
states = "pan";
stateOrigin = getMousePoint(evt);
console.log(value);
}
}
function mouseMove(evt)
{
var pointsLive = getMousePoint(evt);
if(states == "pan")
{
setTranslate(viewport,pointsLive.x - stateOrigin.x, pointsLive.Y - stateOrigin.Y, 1.0); //is this re-intializing every turn?
storeCo[0] = pointsLive.x - stateOrigin.x
storeCo[1] = pointsLive.Y - stateOrigin.Y;
}
else if(states == "store")
{
setTranslate(viewport,storeCo[0],storeCo[1],1); // store the co-ords!!!
stateOrigin = pointsLive; //replaces the old stateOrigin with the new state
states = "stop";
}
}
function mouseUp(evt)
{
if(states == "pan")
{
states = "store";
if(states == "stop")
{
states ='';
}
}
}
In your mousedown function, you are not accounting for the fact that the element might already have a transform and you are just overwriting it.
You are going to need to either look for, and parse, any existing transform. Or an easier approach would be to keep a record of the old x and y offsets and when a new mousedown happens add them to the new offset.

Categories

Resources