I load an XYZ layer as
var layer = new ol.layer.Tile({
title: advanced.name ? advanced.name : "XYZ Layer " + new Date().getTime,
source: source ? source :new ol.source.XYZ({
url: url
})
})
map.addLayer(layer);
It successfully will add the layer, but it doesn't request the tiles until the map is moved, so to the user nothing has changed. Is there a way around this?
Related
I'm creating a custom label maker using Konvajs and everything was working perfectly until I tried to serialize the stage to JSON.
The user creates their custom label in three steps. The first step they select a template image from our library that has a masked area. The second step allows them to upload a personalized image that is placed behind the image that was loaded on the first step. There are external controls that allow the user to scale and move the image so it is rendered with in the masked area. The third step allows them to add text.
I want the user to be able to save their label to their library so they can use it again, but be able to modify any of the three steps. This means I need to serialize the stage to a JSON string, but the image attributes aren't saved in the JSON.
JSON String:
{"attrs":{"width":500,"height":667,"id":"label-maker"},"className":"Stage","children":[{"attrs":{},"className":"Layer","children":[{"attrs":{"name":"template"},"className":"Image"}]},{"attrs":{},"className":"Layer","children":[{"attrs":{"x":160,"y":41.5,"text":"[Enter Name Here]","fontSize":30,"fontFamily":"Calibri","fill":"#555","name":"textundefined","align":"center","draggable":true,"offsetX":114.22119140625},"className":"Text"}]}]}
I'm using the Konvajs toJSON() to serialize my stage.
function save() {
var json = stage.toJSON();
var dataURL = stage.toDataURL('image/png');
//alert(json);
$.ajax({
type: "POST",
url: "label-maker/image-handler.php?action=save",
data: {jsonFileText: json, image: dataURL},
error: function (request, error) {
console.log(arguments);
alert(" Can't do because: " + error);
},
success: function () {
alert(" Done ! ");
}
});
}
By default Konva doesn't save information about image source to JSON. So you have to do this manually.
When you create Konva.Image you can save its source as attribute:
// path is url or base64 string from user's input
imageNode.setAttr('src', path);
Then on deserialization you can load image data from source:
const stage = Konva.Node.create(json, 'container');
stage.find('Image').forEach((imageNode) => {
const src = imageNode.getAttr('src');
const image = new Image();
image.onload = () => {
imageNode.image(image);
imageNode.getLayer().batchDraw();
}
image.src = src;
});
I don't need a concret solution, but someone that gives me a closer hint to solve my problem. I have an ruby on rails 4 intranet application, that is login protected. In this application I have an editing page, where I also use TinyMCE. It has the ability to give it an URL where to send the picture to for uploading it (see here).
I implemented the upload routine with CarrierWave and it works great outside of TinyMCE. If it's possible I would also keep that plugin.
But as I said CarrierWave is currently not working with TinyMCE and an asynchronous upload.
So do you have an idea how I can upload an image, but with correct session token (asynchronously). And the picture URL that not saving the database, but in the text shown in TinyMCE. Is there a plugin that can help me or anything else?
If you need closer information please tell me.
Best regards
Marco
You have to use the image plugin for TinyMCE and set file_picker properties and callbacks, so you can attach files from client-side, rather than URL.
tinymce.init({
// Include image plugin on plugin list
plugins: [ 'image'],
// Include image button on toolbar
toolbar: ['image'],
// Enable title field in the Image dialog
image_title: true,
// Enable automatic uploads of images represented by blob or data URIs
automatic_uploads: true,
// URL of your upload handler
// (YOU SHOULD MAKE AN ENDPOINT TO RECEIVE THIS AND RETURN A JSON CONTAINING: {location: remote_image_url})
images_upload_url: '/text_images',
// Here we add custom filepicker only to Image dialog
file_picker_types: 'image',
// And here's your custom image picker
file_picker_callback: function(cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.onchange = function() {
var file = this.files[0];
// Note: Now we need to register the blob in TinyMCEs image blob
// registry.
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var blobInfo = blobCache.create(id, file);
blobCache.add(blobInfo);
// Call the callback and populate the Title field with the file name
cb(blobInfo.blobUri(), { title: file.name });
};
input.click();
}
});
Add text_images to your route.rb file:
match "text_images" => "text_images#create", via: :post
And create your proccessing action like this:
def create
if params[:file].class == ActionDispatch::Http::UploadedFile
#image = Picture.new(image: params[:file])
respond_to do |format|
if #image.save
format.json { render json: { "location": #image.image.url }.to_json, status: :ok }
else
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
end
This is a very crude implementation, you should make it more secure for your application context, validating and filtering large or invalid files!
UPDATE: There was a recent upgrade on the syntax for new versions of TinyMCE for the onchange function to include a result reader attribute on the create method of the blobCache object:
input.onchange = function() {
var file = this.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
// Note: Now we need to register the blob in TinyMCEs image blob
// registry. In the next release this part hopefully won't be
// necessary, as we are looking to handle it internally.
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var blobInfo = blobCache.create(id, file, reader.result);
blobCache.add(blobInfo);
// call the callback and populate the Title field with the file name
cb(blobInfo.blobUri(), { title: file.name });
};
};
I am trying to display the data from a OData service into a tile where I need to pass some filters to the OData service. I am using the below code however I am getting the error "No template or factory function specified for bindAggregation function of tileContainer".
var tileContainer = new sap.m.TileContainer("tileContainer",{
height:"80%",
allowAdd : true,
editable : false
});
var templateTile = new sap.m.StandardTile("tileTemplate",{
title : 'Orders',
number:'{COUNT}',
info:'Number of Orders',
icon:"sap-icon://bar-chart",
});
oModel = sap.ui.getCore().getModel();
tileContainer.setModel(oModel);
tileContainer.bindAggregation('tiles',{path : "/OrderSet", filters: [f1, f2]}, templateTile);
new sap.m.App({
pages : new sap.m.Page({
enableScrolling : false,
title : "tile container",
content : [tileContainer]
})
}).placeAt("content");
Can some one tell me what am I doing wrong here.
bindAggregation has two parameters; sAggregationName and oBindingInfo and in your code template is passed outside the oBindingInfo object, hence it is not available, which is reason for your error.
You can also pass individual parameters instead of passing them in oBindingInfo object. But in that case sequence of parameters has to be maintained.
Update bindAggregation method's parameter syntax with this
tileContainer.bindAggregation("tiles",{
path: "/OrderSet",
filters: [f1, f2],
template: templateTile
});
In Openlayers 3.9.0 I use loader to get a vector layer from Geoserver. Here is the code
var sourceVector = new ol.source.Vector({
format: new ol.format.GeoJSON(),
loader: function (extent) {
$.ajax('http://localhost:5550/geoserver/mymap/wfs?service=WFS&version=1.0.0&request=GetFeature&typeName=mymap:mylayer&outputFormat=application/json',
{type: 'GET'})
.done(
function(response) {
var geojsonFormat = new ol.format.GeoJSON({});
sourceVector.addFeatures(geojsonFormat.readFeatures(response,{dataProjection :projection,featureProjection : projection}));
})
.fail(function () {alert("BAD");});
},
strategy: new ol.loadingstrategy.tile(ol.tilegrid.createXYZ({maxZoom: 20}))
});
I try to change strategy to strategy: new ol.loadingstrategy.bbox but I get Uncaught TypeError: this.strategy_ is not a function.
Most of the examples set bbox strategy and also a BBOX on the url. If I add ....&BBOX='+extent.join(',') at the end of the url I still get the same error. What am I missing? Is it the strategy, the url, the settings? How do I fix this?
Thanks
You should not initialize a new ol.loadingstrategy.bbox, it is already an ol.LoadingStrategy (unlike ol.loadingstrategy.tile which is a factory returning an ol.LoadingStrategy based on a TileGrid.
// when using the bbox strategy:
strategy: ol.loadingstrategy.bbox
// when using the tile strategy:
strategy: new ol.loadingstrategy.tile(tileGrid)
I am building a ruby on rails app that creates a unique map for each Product model in the database and inserts it into a slide of a flexslider slideshow.
This is working perfectly for json requests that only contain 1 marker. However, when json requests are made with 2 markers, the map's tiles do not render (but both markers are displayed and fit to view).
The rendering issue is solved by moving the "map.fitBounds(featureLayer.getBounds());" into the featureLayer.on('click') function. But I need the functionality to fitBounds after the JSON is loaded rather than on click.
The error I get in the browswer console is: "Uncaught TypeError: Cannot read property 'lat' of undefined" I have searched dozens of threads for help with this, but cannot solve it. I am a newbie to all of this, so your help would be greatly appreciated.
MY JAVASCRIPT
function initProductMap(product) {
var map;
map = L.mapbox.map(document.getElementById(product), 'jasonpearson.ha88l84b');
var featureLayer;
featureLayer = L.mapbox.featureLayer().loadURL('/products/' + product + '.json').addTo(map);
map.scrollWheelZoom.disable();
map.zoomControl.setPosition('bottomright');
featureLayer.on('ready', function() {
map.fitBounds(featureLayer.getBounds());
featureLayer.on('click', function(e) {
e.layer.unbindPopup();
window.open(e.layer.feature.properties.url, '_self');
});
});
$('ul.slides li').show();
map.invalidateSize();
};
MY RAILS CONTROLLER
def show
#product = Product.find(params[:id])
#geojson = Array.new
#product.producers.each do |producer|
#geojson << {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [producer.longitude, producer.latitude]
},
properties: {
name: producer.name,
'marker-color' => '#9f3335',
'marker-symbol' => 'circle',
'marker-size' => 'medium',
url: Rails.application.routes.url_helpers.producer_path(producer)
}
}
]
}
end