I have written script to export my Google spreadsheet to a PDF, but the scale is wrong. I need to set a custom scale of 70%, but as far as I can tell, my options regarding scale customisation are:
1 = Normal 100%,
2 = Fit to width,
3 = Fit to height and
4 = Fit to Page.
Below is some redacted script.
var exporturl = 'https://docs.google.com/spreadsheets/d/' +
'xxxxxx' + //file ID
'/export?exportFormat=pdf&format=pdf' +
'&size=A4' +
'&portrait=true' +
'&scale=3' + // My question refers to this line
'&top_margin=0.50' +
'&bottom_margin=0.50' +
'&left_margin=0.50' +
'&right_margin=0.50' +
'&sheetnames=false&printtitle=false' +
'&pagenum=false' +
'&gridlines=true' +
'&fzr=FALSE' +
'&gid=' +
'yyyyyyy'; //the sheet's Id
Is it possible to set a custom scale or am I bound to the 4 options? Also, if anyone can suggest a workaround, I'd apprecite it.
Related
I have an application I am developing that allows users to drop "Pins" on an SVG. These pins can be moved around the underlying SVG and the coordinates are saved in a database. The pins also have a "center of mass" of bottom center, I store the coordinates of the tip of the pin, not the 0,0 origin of the pin icon.
I am trying to implement a functionality, that will allow the pins to show larger when zoomed out of the underlying SVG, and scale smaller when zooming in (think google maps, if you look at a zoomed out map of all restaurants and then zoom in, the pins get smaller and more spread out).
I have this feature working on desktop web, see images below
However, on mobile, the same code causes the pins to exist in a different location, and when zooming I can see them scaling down to the top left point, and not the center bottom like the desktop client.
JS Code that is creating the scaling styles and logic:
if (instance) {
instance.dispose();
instance = panzoom($('#partialDiv')[0]);
var pins = Array.from(document.querySelectorAll('.draggable'));
instance.on('transform', function(pz) {
var transform = instance.getTransform();
pins.forEach(pin => {
if (transform.scale > 10 && transform.scale < 18) {
pin.setAttribute("transform", 'matrix(' +
15 / transform.scale + ', 0, 0, ' +
15 / transform.scale + ', ' +
pin.transform.baseVal[0].matrix.e + ', ' + pin.transform.baseVal[0].matrix.f + ')');
var pinStyle = pin.style;
pin.setAttribute("transform-origin", "" + pin.getBBox().width / 2 + " " + pin.getBBox().height + "0px");
pinStyle.transformBox = 'fill-box';
pin.style['-webkit-transform-origin-x'] = '50%';
pin.style['-webkit-transform-origin-y'] = 'bottom';
pinStyle.transformBox = 'fill-box';
} else if (transform.scale > 18) {
pin.setAttribute("transform", 'matrix(0.8, 0, 0, 0.8, ' +
pin.transform.baseVal[0].matrix.e + ', ' + pin.transform.baseVal[0].matrix.f + ')');
var pinStyle = pin.style;
pin.setAttribute("transform-origin", "" + pin.getBBox().width / 2 + " " + pin.getBBox().height + "0px");
pinStyle.transformBox = 'fill-box';
pin.style['-webkit-transform-origin-x'] = '50%';
pin.style['-webkit-transform-origin-y'] = 'bottom';
} else {
pin.setAttribute("transform", 'matrix(2, 0, 0, 2, ' +
pin.transform.baseVal[0].matrix.e + ', ' + pin.transform.baseVal[0].matrix.f + ')');
var pinStyle = pin.style;
pin.setAttribute("transform-origin", "" + pin.getBBox().width / 2 + " " + pin.getBBox().height + "0px");
pinStyle.transformBox = 'fill-box';
pin.style['-webkit-transform-origin-x'] = '50%';
pin.style['-webkit-transform-origin-y'] = 'bottom';
}
});
});
}
Why would the pins be displayed at a different origin on Chrome Desktop vs. Chrome IOS? Same is true for other desktop browsers and Safari on mobile. I have tried variations of webkit styles but it does not seem to change this behavior. Any advice is much appreciated.
After hours of troubleshooting I learned that there is a bug on IOS webkit 16.2+ that does not allow transform-origin to work with a transform attribute. Only the transform being performed in CSS will work with a transform-origin style.
Useful resource for anyone having an issue similar to me:
https://caniuse.com/mdn-svg_attributes_presentation_transform-origin
I am trying to add area elements to an image map dynamically. The image is set to display transparently superimposed over a canvas. My goal is to write text on the canvas, use the same coordinates to create the area element on the map, and draw a rectangle on the canvas surrounding the text when the user hovers over the text. (Ultimately I want it to trigger a tooltip, too.) I have done this already with the same map and canvas setup using area elements hardcoded in HTML.
My problem is that I can create the area, appendChild it to the map element and add attributes. However, mousing over the text never triggers the function call to draw the rectangle.
The function used to add the areas to the map (shown as cMap) is "addArea", and the function to draw the rectangle on the canvas (context is ctx) is "labelHover". I have tried every different syntax I have seen demonstrated for adding the .onmouseover attribute to the area, but the alert in the labelHover function never triggers.
function addArea(pX, lY, idX, tipText) {
var labelArea = document.createElement('area');
cMap.appendChild(labelArea);
labelArea.className = "labelArea";
var tlTipID = "tlTip" + idX;
labelArea.id = tlTipID;
labelArea.shape = "rect";
areaCoords = pX + "," + (lY + 42) + "," + (pX + 100) + "," + (lY + 54);
labelArea.coords = areaCoords;
// alert(labelArea.coords);
labelArea.onmouseover = function(){labelHover(pX, lY+42)};
labelArea.onmouseleave = function(){labelLeave(pX, lY+42)};
}
and
function labelHover(ulx,uly) {
ctx.lineWidth = "1";
ctx.strokeStyle = "#ff0000";
ctx.strokeRect(ulx,uly,100,12);
alert(ulx);
}
Thanks for any help.
try this:
labelArea.setAttribute('onmouseover', "labelHover('" + pX + "," + (lY+42) + "')");
labelArea.setAttribute('onmouseout', "labelLeave('" + pX + "," + (lY+42) + "')");
I'm using jcrop and trying to make a "live" preview of the cropped area on an image.
The movement of the selected area works perfectly if the "Crop Selection" area is the same height and width as the destination preview div.
Check out the issue here: http://jsfiddle.net/fbaAW/
function showCoords(c)
{
var $this = this.ui.holder;
var original = $this.prev();
var preview = original.parent().find(".image");
var oH = original.height();
var oW = original.width();
var pH = preview.height();
var pW = preview.width();
var sH = c.h;
var sW = c.w;
var differenceH = pH - sH;
var differenceW = pW - sW;
//preview.css('width', c.w);
//preview.css('height', c.h);
//preview.css("background-size", Math.round(oW + differenceW) + "px" + " " + Math.round(oH + differenceH) + "px");
preview.css("background-position", Math.round(c.x) * -1 + "px" + " " + Math.round(c.y) * -1 + "px");
}
As you can see, I've commented out a few of my tests and attempts at getting this code to work properly but I just can't wrap my head around the relationship between the position and the size background properties in order to get this effect to work correctly.
Calculate the horizontal and vertical ratios between the selection size and the preview area size:
var rW = pW / c.w;
var rH = pH / c.h;
Then apply them to the background-size and background-position:
preview.css("background-size", (oW*rW) + "px" + " " + (oH*rH) + "px");
preview.css("background-position", rW * Math.round(c.x) * -1 + "px" + " " + rH * Math.round(c.y) * -1 + "px");
http://jsfiddle.net/fbaAW/1/
So, if the preview size is, say, 3 times the size of your jCrop selection area, it means you have scale the original image by 3, and compensate for the scaling when defining the background position.
I am working on a force directed graph layout with some added features: selectable links/nodes, tooltips, fisheye effect, and -- important for my question -- zoom and pan.
Now, the zooming works very well like this:
d3 ... .append('svg:g').call(d3.behavior.zoom().on("zoom", redraw))...
Where the redraw function looks like this...
function redraw() {
trans = d3.event.translate;
scale = d3.event.scale;
vis.attr("transform", "translate(" + trans + ")" + " scale(" + scale + ")");
}
However, this method zooms the entire SVG graphic, including font sizes, graph edges, the line stroke-widths surrounding the nodes, etc.
Is it somehow possible not to zoom certain elements? The only solution I have seen so far is to put a line like this (took it from here http://jsfiddle.net/56RDx/2/)
node.attr("font-size", (nodeFontSize / d3.event.scale) + "px");
in the redraw method, to basically invert the zooming on certain elements on the fly. My problem is however (apart from this being an ugly hack), that my edge-widths are dynamically generated on graph-drawing (according to some graph properties...), so this 'invertion' method does not work...
you can add a class to the element you want to trigger the zoom on:
d3 ... .append('svg:g').classed("some_classname", true).call(d3.behavior.zoom().on("zoom", redraw))...
then do:
function redraw() {
trans = d3.event.translate;
scale = d3.event.scale;
vis.selectAll("some_classname").attr("transform", "translate(" + trans + ")" + " scale(" + scale + ")");
}
or you can add a class to all elements you don't want to trigger the zoom on then use the CSS3 :not pseudo-class:
function redraw() {
trans = d3.event.translate;
scale = d3.event.scale;
vis.selectAll("*:not(.some_classname)").attr("transform", "translate(" + trans + ")" + " scale(" + scale + ")");
}
The only solution I could find is an "ugly hack", if (I assume you are) you're trying to not zoom lines for example, the you should try the below, it works for both zooming in and out:
Demo: http://jsfiddle.net/SO_AMK/gJMTb/
JavaScript:
function redraw() {
vis.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
vis.attr("font-size", (nodeFontSize / d3.event.scale) + "px");
vis.selectAll("line.link").style("stroke-width", getStrokeWidth); // Function so it runs for each element individually
}
function getStrokeWidth(){
if (!this.__data__.stroke) { // Doesn't exist, so set it to the original stroke-width
this.__data__.stroke = parseFloat(d3.select(this).style("stroke-width"));
// I found __data__ to be easier than d3's .data()
}
return this.__data__.stroke / d3.event.scale + "px";
}
Please see the documentation for details on using a function with style()
I have a box that previews a Box Shadow. The user types in the inputs for the lenghts, blur, spread and colour (hex). So far I have this for the output of the style but it obviously doesn't work.
document.getElementById('jj_preview3').style["boxShadow"] = jj_input6 + 'px' + jj_input7 + 'px' + jj_input8 + 'px' + jj_input9 + '#' + jj_input10;
jj_input6 = Horizontal Length
jj_input7 = Vertical Length
jj_input8 = Blue Radius
jj_input9 = Spread
jj_input10 = Shadow Colour
What changes do I have to make the the javascript code snippet above to make it work?
It should work if you put in spaces. You're also missing 'px' in the last string literal.
document.getElementById('jj_preview3').style['boxShadow'] = jj_input6 + 'px ' +
jj_input7 + 'px ' + jj_input8 + 'px ' + jj_input9 + 'px #' + jj_input10;
Simply for future references:
var someVariable = document.getElementById("someId")
someVariable.style.boxShadow = "5px 5px 1.2em black";
Note: The 1.2em is for the blur effect, but px could be used as well, or it can be omitted all together.