I use jQuery to change scale of my web page. Here is the code:
<script>
var currFFZoom = 1;
var currIEZoom = 1;
function plus(){
var step = 0.1;
currFFZoom += step;
if (currFFZoom > 10) currFFZoom = 10;
$('body').css('transform','scale(' + currFFZoom + ')');
};
function minus(){
var step = 0.1;
currFFZoom -= step;
$('body').css('transform','scale(' + currFFZoom + ')');
};
</script>
It works fine, but when i increase the scale, some elements moves out of the browser edge and I can't scroll page to them. So, they become unreachable.
PICTURE OF MAILFUNCTION
How I can fix it?
So, I solved the problem. First, I changed
html
{ height: 0%; }
And width needs to be calculated using jquery. This code should be bind to some event handler (button click or something else):
currFFZoom = $('body').css('transform','scale');
$('html').width(currFFZoom*100 + '%');
Worked for me. The whole page is scrollable
I have done quite a few searches here and there. None of them give satisfactory answer, all we know is Google Maps API v3 has a limitation, that if the panTo target is more than 1 window height/width of the current center, it will not be smooth.
Still, I want to achieve "somewhat" smoother, not just "jumping" to the target.
Here is my solution (not perfect but I think it's better than jumping):
Calculate distance between current and target locations
Divide into several sections, each section is a little less than one window
panTo each section to achieve "sectional" smooth animation.
It's fine to find out each section target by the following algorithm:
Current is c(x,y)
Target is t(x,y)
Section count is s
Each section is c(x) + (t(x) - c(x)) / s , c(y) + (t(y) - c(y)) / s
Here is the problem: how to calculate the section count?
It should be based on the current zoom level and window size, right?
Ok, I finally come up with some like this and it works (but did not consider the zoom level)
var distance = Math.sqrt(Math.abs(Math.pow(lastLocation.lat() - status.Lat, 2)) + Math.abs(Math.pow(lastLocation.lng() - status.Lng, 2)));
//console.info('last:' + lastLocation.lat() + ',' + lastLocation.lng());
//console.info('new:' + status.Lat + ',' + status.Lng);
//console.info('distance:' + distance);
var smoothFactor = 8.0 / 1440; //hard code for screen size without considering zoom as well...
var factor = $(window).width() * smoothFactor;
smoothPanSections = [];
var sectionCount = Math.ceil(distance / factor);
var sectionLat = (status.Lat - lastLocation.lat()) / sectionCount;
var sectionLng = (status.Lng - lastLocation.lng()) / sectionCount;
for (var i = 1; i <= sectionCount; i++) {
if (i < sectionCount) {
smoothPanSections.push({ Lat: lastLocation.lat() + sectionLat * i, Lng: lastLocation.lng() + sectionLng * i });
}
else
smoothPanSections.push({ Lat: status.Lat, Lng: status.Lng });
}
panStatus();
And the panStatus is:
function panStatus() {
if (smoothPanSections.length > 0) {
var target = smoothPanSections.shift();
//still have more sections
if (smoothPanSections.length > 0) {
google.maps.event.addListenerOnce(map, 'idle', function () {
window.setTimeout(function () {
panStatus();
}, 100);
});
}
var location = new google.maps.LatLng(target.Lat, target.Lng);
map.panTo(location, zoomSize);
}
}
I am quite new to Openlayers and was wondering if there is a method or event that returns the zooming direction, e.g. onzoomin/onzoomout events. I am using sproutcore 1.0 and trying to modify a feature font according to the zooming level. I tried working with Rules but according to the application structure this does not work. Here is my sample event of what I want to do:
this.map.events.on({ "zoomend": function (e) {
var sub = 0;
if (ZOOMOUT){
sub = this.getZoom();
} else {
sub = this.getZoom() * -1;
}
var font = myFeature.layer.styleMap.styles['default'].defaultStyle.fontSize;
font = font + sub*10;
myFeature.layer.redraw();
}});
Found a workaround using geometry bounds which gives a good result:
this.map.events.on({ "zoomend": function (e) {
var width = myFeature.geometry.bounds.right - myFeature.geometry.bounds.left;
var div = 0;
if (this.getZoom() > 12) {
div = 4;
} else {
div = 6;
}
myFeature.layer.styleMap.styles['default'].defaultStyle.fontSize = (width/((15 - this.getZoom())+1)) / div).toString() + "px";
myFeature.layer.redraw();
}});
I need to create something like this:
http://www.mrporter.com/journal/journal_issue71/2#2
where every product in my big image is associated with a tooltip which appears on mouse hover.
But I need this to work with fullscreen images.
The first solution I thought (as the example above) is the map html solution where each fill up exactly the boundaries of my products.
The problem is that I can't indicate precise values for my because my image size depends on window screen.
The best solution would be the possibility to set percentage values for my area.
Is this possible? Any other suggestions ?
Alternative solution using links:
CSS:
.image{
position: relative;
}
.image a{
display: block;
position: absolute;
}
HTML:
<div class="image">
<img src="image.jpg" alt="image" />
</div>
Percentage dimensions can be detected in graphic editors
There is a jQuery plugin for this jQuery RWD Image Maps.
You might want to integrate my pending pull request (manually) to support "width=100%": https://github.com/stowball/jQuery-rwdImageMaps/pull/10
you can check this this plugin is life saving.
Useful when you want to map a percentage scaled image etc.
It can be used with or without jQuery.
https://github.com/davidjbradshaw/imagemap-resizer
and you can see it working at.
http://davidjbradshaw.com/imagemap-resizer/example/
Because this can't be done with simple HTML/CSS manipulation, the only alternative is JavaScript to, effectively, recalculate the coordinates based on the resizing of the image. To this end I've put together a function (though there's two functions involved) that achieves this end:
function findSizes(el, src) {
if (!el || !src) {
return false;
}
else {
var wGCS = window.getComputedStyle,
pI = parseInt,
dimensions = {};
dimensions.actualWidth = pI(wGCS(el, null).width.replace('px', ''), 10);
var newImg = document.createElement('img');
newImg.src = src;
newImg.style.position = 'absolute';
newImg.style.left = '-10000px';
document.body.appendChild(newImg);
dimensions.originalWidth = newImg.width;
document.body.removeChild(newImg);
return dimensions;
}
}
function remap(imgElem) {
if (!imgElem) {
return false;
}
else {
var mapName = imgElem
.getAttribute('usemap')
.substring(1),
map = document.getElementsByName(mapName)[0],
areas = map.getElementsByTagName('area'),
imgSrc = imgElem.src,
sizes = findSizes(imgElem, imgSrc),
currentWidth = sizes.actualWidth,
originalWidth = sizes.originalWidth,
multiplier = currentWidth / originalWidth,
newCoords;
for (var i = 0, len = areas.length; i < len; i++) {
newCoords = areas[i]
.getAttribute('coords')
.replace(/(\d+)/g,function(a){
return Math.round(a * multiplier);
});
areas[i].setAttribute('coords',newCoords);
}
}
}
var imgElement = document.getElementsByTagName('img')[0];
remap(imgElement);
JS Fiddle demo.
Please note, though, that this requires a browser that implements window.getComputedStyle() (most current browsers, but only in IE from version 9, and above). Also, there are no sanity checks other than ensuring the required arguments are passed into the functions. These should, though, be a start if you want to experiment.
References:
document.body.
document.createElement().
document.getElementsByName().
document.getElementsByTagName().
element.getAttribute().
element.setAttribute().
element.style.
Math.round().
node.appendChild().
node.removeChild().
parseInt().
string.replace().
string.substring().
window.getComputedStyle.
Percentages in image maps are not an option. You might want to get some scripting involved (JS) that recalculates the exact position on images resize. Of course, in that script you can work with percentages if you want.
Consider using the Raphaël JavaScript Library with some CSS. See http://raphaeljs.com/ and Drawing over an image using Raphael.js.
I know this is an old question but maybe someone needs this at some point as I did. I modified #David Thomas' answer a bit to be have this little piece of JS be able to handle future recalculations:
function findSizes(el, src) {
if (!el || !src) {
return false;
}
else {
var wGCS = window.getComputedStyle,
pI = parseInt,
dimensions = {};
dimensions.actualWidth = pI(wGCS(el, null).width.replace('px', ''), 10);
var newImg = document.createElement('img');
newImg.src = src;
newImg.style.position = 'absolute';
newImg.style.left = '-10000px';
document.body.appendChild(newImg);
dimensions.originalWidth = newImg.width;
document.body.removeChild(newImg);
return dimensions;
}
}
function remap(imgElem) {
if (!imgElem) {
return false;
}
else {
var mapName = imgElem
.getAttribute('usemap')
.substring(1),
map = document.getElementsByName(mapName)[0],
areas = map.getElementsByTagName('area'),
imgSrc = imgElem.src,
sizes = findSizes(imgElem, imgSrc),
currentWidth = sizes.actualWidth,
originalWidth = sizes.originalWidth,
multiplier = currentWidth / originalWidth,
newCoords;
for (var i = 0, len = areas.length; i < len; i++) {
// Save original coordinates for future use
var originalCoords = areas[i].getAttribute('data-original-coords');
if (originalCoords == undefined) {
originalCoords = areas[i].getAttribute('coords');
areas[i].setAttribute('data-original-coords', originalCoords);
}
newCoords = originalCoords.replace(/(\d+)/g,function(a){
return Math.round(a * multiplier);
});
areas[i].setAttribute('coords',newCoords);
}
}
}
function remapImage() {
var imgElement = document.getElementsByTagName('img')[0];
remap(imgElement);
}
// Add a window resize event listener
var addEvent = function(object, type, callback) {
if (object == null || typeof(object) == 'undefined') return;
if (object.addEventListener) {
object.addEventListener(type, callback, false);
} else if (object.attachEvent) {
object.attachEvent("on" + type, callback);
} else {
object["on"+type] = callback;
}
};
addEvent(window, "resize", remapImage);
has anyone noticed or found a solution to the problem I've been experiencing? It takes a long time to render large fonts (>100px) in Chrome on the canvas using fillText(). I need to have a much faster frame rate, but once the fonts get big it take like a second to load each frame. In firefox it runs well though...
UPDATE:
Here is the pertinent code that is running in my draw() function which runs every 10 milliseconds on interval. If anything pops out to you, that would be great. I'll try to profiler thing though, thanks.
g.font = Math.floor(zoom) + "px sans-serif";
g.fillStyle = "rgba(233,233,245," + (ZOOM_MAX-zoom*(zoom*0.01))/(ZOOM_MAX) + ")";
for (h=0; h<76; h++)
{
h_offset = 2.75*h*Math.floor(zoom);
// only render if will be visible, because it tends to lag; especially in Chrome
hpos = Math.floor(half_width + std_offset + h_offset);
if (hpos > (-half_width)-h_offset && hpos < WIDTH+h_offset)
{
g.fillText(1950+h, hpos, anchor_y - 0);
}
}
g.font = "600 " + Math.floor(zoom/40) + "px sans-serif";
g.fillStyle = "rgba(233,233,245," + (ZOOM_MAX-zoom*(zoom*0.0001))/(ZOOM_MAX) + ")";
for (h=0; h<76; h++)
{
h_offset = 2.75*h*Math.floor(zoom);
hpos = Math.floor(half_width + std_offset + h_offset);
if (hpos > (-half_width)-h_offset && hpos < WIDTH+h_offset)
{
// see if we should bother showing months (or will it be too small anyways)
if (zoom/40 > 2)
{
// show months
for (i=0; i<12; i++)
{
i_offset = 0.175*i*zoom;
ipos = Math.floor(WIDTH/2 + std_offset + i_offset + h_offset) + 10;
if (ipos > -half_width && ipos < WIDTH)
{
g.fillText(months[i], ipos, anchor_y - 20);
}
}
}
}
}
g.font = "600 " + Math.floor(zoom/350) + "px sans-serif";
g.fillStyle = "rgba(233,233,245," + (ZOOM_MAX-zoom/5)/(ZOOM_MAX*2.25) + ")";
for (h=0; h<76; h++)
{
h_offset = 2.75*h*Math.floor(zoom);
// only render if will be visible, because it tends to lag; especially in Chrome
hpos = Math.floor(half_width + std_offset + h_offset);
if (hpos > (-half_width)-h_offset && hpos < WIDTH+h_offset)
{
// see if we should bother showing months (or will it be too small anyways)
if (zoom/40 > 2)
{
// show months
for (i=0; i<12; i++)
{
i_offset = 0.175*i*zoom;
ipos = Math.floor(WIDTH/2 + std_offset + i_offset + h_offset) + 10;
// see if we should bother showing days (or will it be too small anyways)
if (zoom/350 > 2)
{
// show days
for (j=0; j<31; j++)
{
j_offset = 0.005*j*zoom + zoom*0.005;
jpos = Math.floor(half_width + std_offset + j_offset + i_offset + h_offset);
if (jpos > -half_width && jpos < WIDTH)
{
g.fillText(days[i][j], jpos, anchor_y - 20);
selected_days += 'm: '+i+', d: '+j+' | ';
}
}
}
}
}
}
}
We'd need a lot more information, I'm not convinced that drawing a large font is actually whats causing the performance issues. Drawing such a large font works extremely quickly on my machines for any browser that I've tried.
The first thing you should do is open up the Chrome profiler and then run the code, and see if it is actually the ctx.fillText call that is taking up the time. I imagine its actually something else.
It's possible you are calling something too much, like setting ctx.font over and over unnecessarily. Setting ctx.font on some browsers actually takes significantly longer to do than calls to fillRect! If your font changes in the app you can always cache.
Here's a test back from October: http://jsperf.com/set-font-perf
As you can see, in many versions of Chrome setting the font unnecessarily doubles the time it takes! So make sure you set it as little as possible (with caching, etc).