Rectangular Grid Using Google Apps Script in Google Slides - google-apps-script

So, I asked ChatGPT to create a rectangular grid using Google Apps Script within Google Slides. Here are the parameters I gave it: The grid has 5 columns and 4 rows, with each rectangle being no more than 20% of the width of the grid, which is 1880px wide. The rectangles are separated by 20px margins and the slide itself has 20px margins on the outside. It sort of worked, but I had to adjust the width and height in the script because the rectangles went beyond the width and height of the 1920 x 1080 slide. Also, when I adjust the margin and number of columns, it doesn't fit exactly like I want it to. Here's the code below that it gave me...
function createGrid() {
var slideWidth = 1440;
var slideHeight = 810;
var margin = 20;
var numRows = 4;
var numColumns = 6;
var maxRectWidth = slideWidth * 0.2; // Each rectangle is no more than 20% of the width of the grid
var rectWidth = Math.min((slideWidth - margin * 2 - margin * (numColumns - 1)) / numColumns, maxRectWidth);
var rectHeight = (slideHeight - margin * 2 - margin * (numRows - 1)) / numRows;
// Create new slide and set dimensions
var presentation = SlidesApp.getActivePresentation();
var slide = presentation.appendSlide();
slide.selectAsCurrentPage();
// Create grid of rectangles
for (var row = 0; row < numRows; row++) {
for (var column = 0; column < numColumns; column++) {
var x = margin + column * (rectWidth + margin);
var y = margin + row * (rectHeight + margin);
var shape = slide.insertShape(SlidesApp.ShapeType.RECTANGLE, x, y, rectWidth, rectHeight);
shape.getBorder().setTransparent();
shape.getFill().setSolidFill('#777777');
}
}
}
Here's a screenshot of the grid it gave me. I had to adjust the SlideWidth and SlideHeight to get it to work.
So, I know that the math is wrong with the formula it's using in lines 7-9 of the script, but I'm not smart enough to change it so that no matter what margins I put in there, or number of columns or rows, it would fit within the 1920 x 1080 slide with 20px margins on the outside of the slide.
Would any of you know how to edit this script so that no matter what margin, or number of rows or columns I put in there, the rectangular grid would fit within a 1920 x 1080 slide with 20px margins on the outside?
Here's a link to make your own copy to view the script and its result.

Are you sure about the size of the slide? What if a different browser produces a smaller slide. Why not try this.
Replace this:
function createGrid() {
var slideWidth = 1440;
var slideHeight = 810;
.
.
.
// Create new slide and set dimensions
var presentation = SlidesApp.getActivePresentation();
With this:
function createGrid() {
var presentation = SlidesApp.getActivePresentation();
var slideWidth = presentation.getPageWidth();
var slideHeight = presentation.getPageHeight();
.
.
.
// Create new slide and set dimensions
// Make sure you delete or comment out the following line
// var presentation = SlidesApp.getActivePresentation();

Related

How to make an image smaller while leaving the it in it's original proportions?

I'm trying to add a list of images from my Google drive to a Google doc using Google apps script.
I made a list named images_list of links to the images that are in my Drive.
I was able to add all the content I need to the doc and the images at the end of it.
Currently the images are huge in their size, and I turned it into 400X400.
The problem is that not all them are square.
How can I make the image smaller while leaving the image in it's original proportions?
This is the code I'm using:
if(images_list[0]){
for(var i=0; i<images_list.length; i++){
try{
var imageID = images_list[i].slice(32,65);
var blob = DriveApp.getFileById(imageID).getBlob();
var imgDoc = body.appendImage(blob);
imgDoc.setWidth(400).setHeight(400)
bullet_index = bullet_index+1
}catch(e){}
}
}
Thanks!
For example it could be something like this:
if (images_list[0]) {
for (var i = 0; i < images_list.length; i++) {
try {
var imageID = images_list[i].slice(32, 65);
var blob = DriveApp.getFileById(imageID).getBlob();
var max = 400;
var w = imgDoc.getWidth();
var h = imgDoc.getHeight();
if (w > h) { h = h * (max / w); w = max }
else { w = w * (max / h); h = max }
imgDoc.setWidth(w).setHeight(h);
bullet_index = bullet_index + 1
} catch (e) { }
}
}
It will fit any image into a square 400x400 px while keeping the aspect ratio.

Fit array of movieclips in a fixed box in AS3

I have this array of movieclips (there can be only one but there can also be like 100) and a big movieclip on the stage with a fixed width and height (it can't be resized).
var boxWidth:int = 500
var boxHeight:int = 300
var box:MovieClip = new Movieclip;
box.graphics.beginFill(0x444444);
box.graphics.drawRect(
0,
0,
boxWidth,
boxHeight
);
box.graphics.endFill();
addChild(box);
var movieClipsArray:Array = []; //dynamic number of movieclips
var movieClipsSpacing:int = 10;
for(var i:String in movieClipsArray){
//calculate x, y, width, and height
box.addChild(movieClipsArray[i]);
}
How can I add all the movieclips from the array to the box, while fullfilling the following requirements?
The movieclips may be resized, but they have to keep their height/width ratio
The movieclips may not overlap
The movieclips may not exceed the borders of the box movieclip
There has to be some space between the movieclips (let's say, 10px)
The space of the box movieclip has to be used as efficiently as possible
The movieclips don't have to be in the same order, e.g movieClipsArray[0] could be at the left top, but also in the right bottom or somewhere in the center
I'm sorry for not having done much myself, but I just don't have any idea where to start
Dunno if I'm over complicating this at all, but I'd personally do something like this:
var boxWidth:int = 500;
var boxHeight:int = 300;
// each column and row of equally sized movieclip would be 5/7 and 3/7 of the width/height of the box respectively.
mcColumns = ((movieClipsArray.length / 7) * 5); // tells you how many columns
mcRows = ((movieClipsArray.length / 7) * 3); // tells you how many rows
//calculate width
var availableWidth = boxWidth - (mcColumns * 10); //width available after 10px spaces
var mcWidth:int = availableWidth / mcColumns; //width of each box
//calculate height
var availableHeight = boxHeight - (mcRows * 10); //height available after 10px spaces
var mcHeight:int = availableHeight / mcRows; //height of each box
for(var i:int = 0; i<mcColums; i++;){
for(var j:int = 0; i<mcRows; i++;){
//calculate x
movieClipsArray[i+j].width = mcWidth;
movieClipsArray[i+j].x = (availableWidth / mcWidth) * i;
movieClipsArray[i+j].x += 10 * i; //adds the space
//calculate y
movieClipsArray[i+j].height = mcHeight;
movieClipsArray[i+j].y = (availableHeight /mcWidth) * j;
movieClipsArray[i+j].y += 10 * j; //adds the space
box.addChild(movieClipsArray[i+j]);
}
}
Please bear in mind that I haven't checked this, I just wrote it to help set you on the right track.

SVG Raphaeljs Creating a grid of rectangles

I want to create a user defined grid of rectangles using SVG Raphaeljs. The method I am using at the moment is close to what I want it to do but its clearly not right.
My code as of now :
Creating the rectangles and trying to get them placed in an even grid of equal distance from each other
function startup() {
var paper = Raphael(50, 50, 1500, 875);
for (var i = 0; i <= 7; i++) {
for (var j = 0; j <= 4; j++) {
var offset = i; // Stores the number to remove from the next variable to keep an even distance between shapes
var moveRight = (i + 20 - offset) * i; // new variable stores the amount to move the next rectangle along by adding 20 (distance in pixels
// to move to the right) to the loop counter i and then subtracting the offset which is the variable i
// before the + 20 was added and then multiplying it all by i again.
var moveDown = (j + 35 - offset) * j;
var c = paper.rect(moveRight, moveDown, 15, 20);
c.attr("fill", "#f00");
c.attr("stroke", "#fff");
}
}
}
The above currently produces this wonky grid as a result of my poor coding.
I need this to work in such a way that the user can enter the actual amount of rows and columns just by editing the values I put into the for loops and then using that number to change the distance each shape is placed,
As you can see I tried to do this by making a rough formula but I am now stuck, so any help is appreciated.
Ok, silly on my part. I've noticed a mistake and I've amended my code to the following:
function startup() {
var paper = Raphael(50, 50, 1500, 875);
for (var i = 0; i <= 7; i++) {
for (var j = 0; j <= 4; j++) {
var offseti = i; // Stores the number to remove from the next variable to keep an even distance between shapes
var moveRight = (i + 20 - offseti) * i; // new variable stores the amount to move the next rectangle along by adding 20 (distance in pixels
// to move to the right) to the loop counter i and then subtracting the offset which is the variable i
var offsetj = j; // before the + 20 was added and then multiplying it all by i again.
var moveDown = (j + 25 - offsetj) * j;
var c = paper.rect(moveRight, moveDown, 15, 20);
c.attr("fill", "#f00");
c.attr("stroke", "#fff");
}
}
}

How to Calculate Center pixels(x,y) of each small square drwan within a rectangle in HTML5 canvas

I have written a code that will create a rectangle and by providing values it will generate rows and columns in that rectangle,basically it is creating small squares within that rectangle.
Code can be seen here http://jsfiddle.net/simerpreet/ndGE5/1/
<h1>Example</h1>
<canvas id="t_canvas" style="border:1px solid #000000;" width="300" height="225"></canvas>
<br/>
<button id="draw">Draw</button>
<Script>
var x=50;
var y=50;
var w = 150; //width
var h = 100; //height
var columns=3;
var rows =3;
var vnp =w/columns; //vertical next point
var hnp=h/rows; //horizontal next point
var canvas = document.getElementById("t_canvas");
var ctx = canvas.getContext("2d");
$(document).ready(function() {
$('#draw').click(function() {
drawVerticalLines(parseFloat(vnp));
drawHorizontalLines(parseFloat(hnp));
ctx.fillStyle = "#FF0000";
ctx.strokeRect(x, y, w, h);
ctx.stroke();
});
});
function drawVerticalLines(np){
var np = x + np //start point of first column
while(np < w+x){
ctx.moveTo(np, y);
ctx.lineTo(np, y+h);
np = vnp + np;
}
}
function drawHorizontalLines(np){
var np = y + np //start point of first column
while(np < h+y){
ctx.moveTo(x, np);
ctx.lineTo(x+w, np);
np = hnp + np;
}
}
<script>
I have given the value of rows =3 and columns =3, so it will create a tic tac toe like squares.My requirement is when i click in a any small square at any postion,it should give me the exact center location of that particular square, iam kind of stuck here,is there any kind of algorithm which can do this?
Thanks,
Simer
The correct way to get the center point can be manifested in various ways but in essence this is what you need to do:
var mousePos = getMousePos(canvas, evt), // get adjusted mouse position
gw = vnp * 0.5, // get center of one cell
gh = hnp * 0.5,
ix = ((mousePos.x - x) / vnp)|0, // get cell index clicked
iy = ((mousePos.y - y) / hnp)|0,
cx = ix * vnp + x + gw, // scale up to get pixel position
cy = iy * hnp + y + gh;
Modified fiddle here
A quick breakdown of the following lines (showing only for x, same is for y):
ix = ((mousePos.x - x) / vnp)|0
cx = ix * vnp + x + gw
Adjust for grid by subtracting the grid's start point from the mouse position. This gives you the position within the grid:
mousePos.x - x
Quantize the value to get an index by using a single cell's width. The |0 cuts off the fractional value so we end up with an integer value which we need for the next step:
((mousePos.x - x) / vnp)|0
Now that we have an integer index [0, 2] (you need to do boundary checks or index range check for the grid) we simply multiply it with a cell width to get a pixel position for the start of a grid cell:
cx = ix * vnp
And finally add back the grid start position of the grid to get to the cell's on-screen corner as well as adding half a cell size to get center of this cell:
cx = ix * vnp + gw
A bonus is that you now have indexes (ix and iy) you can use with an array to more easy check game status.

Actionscript 3: Dynamically adding movieclips constrained to a container

Last Edit: Resolved!
Well, i was unable to find the ENTIRE answer here but i finally got what i was after. thanks very much for all of your help and patience.
as a side note: i think i may have been having problems with using the int and Number types, upon closer inspection of my solution, i realised that Number was being used and not int. turns out number contains floating points and int doesn't. my numbers were probably rounding whenever i tried to fix this my self. for all i know, TDI's answer might have been spot on and the use of int for the padding might have accumulated rounded numbers.. Oh well, you learn something every day..
the correct code to constrain movie clips to a container movie clip (or sprite or whatever) in the fashion i was looking for is this:
var picContainer:PicContainer = new PicContainer();
picContainer.x = stage.stageWidth / 2 - picContainer.width / 2;
picContainer.y = stage.stageHeight / 2 - picContainer.height / 2;
addChild(picContainer);
var totalPics:int = 17;
var pic:Pic = new Pic(); //make an instance just to get its width
var xRange:Number = picContainer.width - pic.width;
var spacing:Number = xRange / (totalPics - 1);
//A little optimization: only need to calculate this number ONCE:
var yLoc:Number = picContainer.height / 2 - pic.height / 2;
for(var i:int = 0; i < totalPics; i++) {
pic = new Pic();
pic.x = i * spacing;
pic.y = yLoc;
picContainer.addChild(pic);
}
the logic is pretty simple, and i don't know why i couldn't get it my self, because i drew diagrams that say exactly this logic. however, i must not have put the numbers in the right places or i wouldn't have had to ask, would i ;P
BONUS CONTENT!
as an added bonus (if anyone finds this thread looking for answers..)
you could also have the 'pic's fan out from the center point (but they'd still be in order of left to right) by using this code:
var picContainer:PicContainer = new PicContainer();
picContainer.x = stage.stageWidth / 2 - picContainer.width / 2;
picContainer.y = stage.stageHeight / 2 - picContainer.height / 2;
addChild(picContainer);
var totalPics:int = 5;
var pic:Pic = new Pic(); //make an instance just to get its width
var padding:Number = (picContainer.width - (pic.width * totalPics)) / (totalPics + 1);
for(var i:int = 0; i < totalPics; i++) {
pic = new Pic();
pic.x = padding + i * (pic.width + padding);
pic.y = picContainer.height / 2 - pic.height / 2;
picContainer.addChild(pic);
}
Try it out, these make for great thumbnail dock engines!
First Edit: Well, there is some progress thanks to TDI but not a complete solution.
you see, the problem remains that the movie clips do not squash completely into the container, the last one or two are left sticking out.
example:
my revised code looks like this:
var newPicContainer:picContainer = new picContainer();
var newPic:pic;
var picwidth:int = 100;
var amountofpics:int = 22;
var i:int;
//add a container
addChild(newPicContainer);
//center our container
newPicContainer.x = (stage.stageWidth/2)- (newPicContainer.width/2);
newPicContainer.y = (stage.stageHeight/2)- (newPicContainer.height/2);
var totalpicwidth:int = picwidth*amountofpics;
var totalpadding:int = newPicContainer.width - totalpicwidth;
var paddingbetween:int = (totalpadding / amountofpics);
for (i = 0; i < amountofpics; ++i)
{
//make a new mc called newPic(and i's value) eg. newPic1
this['newPic' + i] = new pic();
this['newPic' + i].width = picwidth;
//add our pic to the container
newPicContainer.addChild(this['newPic' + i]);
//set the new pics X
if (i != 0)
{
// if i is not 0, set newpic(i)s x to the previous pic plus the previous pics width and add our dynamic padding
this['newPic' + i].x = this['newPic' + (i-1)].x + picwidth + paddingbetween;
}
else
{
this['newPic' + i].x = 0;
}
}
thanks again to anyone in advance!
Original Post:
Hello, First time posting here. I hope I'm not getting anything wrong . my problem is as follows:
I've got a pretty basic for loop that creates a 'thumbnail' and puts it next to the previous one (With a little padding) inside a containing movie clip.
var newPicContainer:picContainer = new picContainer();
var newPic:pic;
var amount:int = 9;
var i:int;
//Add our container
addChild(newPicContainer);
//center our container
newPicContainer.x = (stage.stageWidth/2)- (newPicContainer.width/2);
newPicContainer.y = (stage.stageHeight/2)- (newPicContainer.height/2);
for (i = 0; i < amount; ++i)
{
newPic = new pic();
newPicContainer.addChild(newPic);
//just so i know it's adding them..
trace(newPic.thisOne);
newPic.thisOne = i;
// set this one to its self (+5 for padding..) Times, the amount already placed.
newPic.x = (newPic.width+5) *i;
}
I'm wondering if there is some equation or 'magic math' that I can use to figure out what the length of the container is and have the 'thumbnails' be added relative to that number. basically squashing the thumbnails against each other to make them all fit inside..
something along the lines of:
newPic.x = (newPic.width *i) - stuff here to make it know not to go past the containing width;
I must admit i'm not too great with math and so this part of coding escapes me..
thanks to any takers in advance..
you can get the length of your container by either calling its width property explicitly:
//Container Width
newPicContainer.width;
or the newContainer is also the parent of the added pics:
//Container Width
newPic.parent.width;
then you need to get the total length occupied by you pics:
var arrayOfPics:array = [pic1, pic2, pic3, pic4, pic5];
var picsWidth:Number;
for each (var element:pic in arrayOfPics)
picsWidth =+ element.width;
after than you can subtract the length of the total pics from the container to know your available padding for separation:
var totalPadding:Number = newPicContainer.width - picsWidth;
now you can determine how much padding you can afford between the pics and both sides of the container by dividing the totalPadding by the number of pics, and add an extra padding for the end.
var padding:Number = totalPadding / arrayOfPics.length + 1;
now you can simply add your pics by including the padding
for (var i:int = 0; i < arrayOfPics.length; i++)
{
newPicContainer.addChild(arrayOfPics[i]);
(i == 0) ? arrayOfPics[i].x = padding : arrayOfPics[i].x = arrayOfPics[i - 1].x + arrayOfPics[i - 1].width + padding;
}
Try this...
//maximum available length
var maxLength:int;
// a single thumbnail width
var picWidth:int = 100;
// total number of pics in a container
var maxNumPics:int;
// as long as the maximum available length
// is inferior to the container length
// add a new thumbnail
while( maxLength < newPicContainer.length - 100 )
{
maxLength += 100;
maxNumPics += 1;
}
// calculate the amount of available padding.
var padding:Number = ( newPicContainer.length - maxLength )/ maxNumPics;
//add your thumbs
var picX:int;
for( var i:int ; i < maxNumPics ; ++i )
{
var newPic:Pic = new Pic();
newPic.x = picX;
picX += padding + picWidth;
newPicContainer.addChild( newPic );
}
I'd recommend you look at using the Flex framework (it's a Flash framework), it will make building this sort of view much easier.
You can set a container's layout property, so that items are placed in horizontal, vertical or tiled layouts, and then just add items to the container.
For more info on Flex look here
For info on Flex Layouts