So I've been trying to load a remote image using titanium, here's a snippet that I'm using, but it always shows the default image. Any clue what I am doing wrong, I'm sorry it's a naive question
here's my view
<View id="image">
</View>
and my controller
userImage = Ti.UI.createImageView({
id : "userImage",
image : "http://graphics.ucsd.edu/~henrik/images/imgs/face_bssrdf.jpg",
width : 90,
center:0,
height : 90,
});
$.image.add(userImage);
had to upgrade the sdks was buggy at 4.0.0.RC
The following code works fine for me with 4.0.0.GA and 4.1.0.GA:
var win = Ti.UI.createWindow({
backgroundColor: 'green'
});
var userImage = Ti.UI.createImageView({
id: "userImage",
image: "http://graphics.ucsd.edu/~henrik/images/imgs/face_bssrdf.jpg",
width: 90,
center: 0,
height: 90,
});
win.add(userImage);
win.open();
Related
Would you please advice where I could find explanation about Group({insert:true}) option as I could not find it in reference? How does this option work and if someone had made that example he should be able to read about it somewhere. Thanks.
This item constructor option is an internal API that doesn't really have a public use case, this is why you didn't find it in the documentation.
It is mainly used for internal operations and testing purpose.
It is true by default and if you set it to false, the consequence is that the created item will not be inserted into the scene graph, meaning you won't see it on the screen.
Look at this sketch for a demonstration.
// This item will be inserted as a child of the active layer.
const itemInserted = new Path.Circle({
center: view.center - 50,
radius: 50,
fillColor: 'orange'
});
// This item will not be inserted in the scene graph.
const itemNotInserted = new Path.Circle({
center: view.center + 50,
radius: 50,
fillColor: 'blue',
insert: false
});
I'm trying to build a widget in Jupyter Notebook that uses Fabric.js (http://fabricjs.com/), however I'm getting an error that is a blocker for me. The most basic solution I need is just to make the widget output a canvas with an interactive red rectangle, like what you find on the Fabric.js homepage:
What I've tried so far:
I started from the basic "Hello World" tutorial (https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Custom.html) which is the basis for the four cells below, and I tried to add a simple example from the fabric node webpage to create a red rectangle. Here are the cells I have in Jupyter notebook:
Cell 1:
%%HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.min.js" type="text/javascript"></script>
Cell 2:
import ipywidgets as widgets
from traitlets import Unicode, validate
class HelloWidget(widgets.DOMWidget):
_view_name = Unicode('HelloView').tag(sync=True)
_view_module = Unicode('hello').tag(sync=True)
_view_module_version = Unicode('0.1.0').tag(sync=True)
Cell 3:
%%javascript
require.undef('hello');
define('hello', ["#jupyter-widgets/base"], function(widgets) {
var HelloView = widgets.DOMWidgetView.extend({
render: function() {
var canvas = document.createElement('canvas');
canvas.id = 'canvas';
canvas.width = 1000;
canvas.height = 500;
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
this.el.appendChild(canvas);
var fabricCanvas = new fabric.Canvas(canvas);
var rect = new fabric.Rect({
top : 100,
left : 100,
width : 60,
height : 70,
fill : 'red'
});
fabricCanvas.add(rect);
},
});
return {
HelloView : HelloView
};
});
Cell 4:
HelloWidget()
However, I unfortunately get the following error in the JS console and it doesn't make the red square:
Please help me fix the code to make it work!
My problem was I didn't understand how require.js works... :/
Here's how I fixed the problem:
%%javascript
require.undef('hello');
require.config({
//Define 3rd party plugins dependencies
paths: {
fabric: "https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.min"
}
});
define('hello', ["#jupyter-widgets/base", 'fabric'], function(widgets) {...
I have a simple meteor app with two templates using flowrouter to navigate between them. Each template has a single HTML canvas element in it both have a fabricjs canvas assigned and a box drawn.
When I navigate between the two templates while doing a memory performance profile I see the memory continuously increase at every navigation between templates.
I expected the garbage collector to clean up the canvas vars but its not. So something keeping them in context. I can't see what I'm missing here.
Template HTML
<template name="one">
Template One
two
<div>
<canvas id="canvasONE" width="2000" height="1601"></canvas>
</div>
</template>
<template name="two">
Template Two
one
<div>
<canvas id="canvasTWO" width="2000" height="1601"></canvas>
</div>
</template>
// JavaScript
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import './main.html';
//////////////////////////////////////////////
// Template One
Template.one.onRendered( function(){
var canvas = new fabric.Canvas('canvasONE',{selection:true});
var rec = new fabric.Rect({
left: 0,
top: 0,
width: 120,
height: 50,
rx: 4,
ry: 4,
fill: '#64b5f6',
stroke: '#6Ebfff',
strokeWidth: 2,
originX: 'left',
originY: 'top',
lockScalingX: true,
lockScalingY: true
});
canvas.add(rec)
})
/////////////////////////////////////////////////////
// Template Two
Template.two.onRendered( function(){
var canvas = new fabric.Canvas('canvasTWO',{selection:true});
var rec = new fabric.Rect({
left: 0,
top: 0,
width: 120,
height: 50,
rx: 4,
ry: 4,
fill: '#223344',
stroke: '#6Ebfff',
strokeWidth: 2,
originX: 'left',
originY: 'top',
lockScalingX: true,
lockScalingY: true
});
canvas.add(rec)
})
Thanks...
UPDATE: after a few hours debugging, it appears to be DOM related. The meteor template removes the DOM elements but fabric could still be referencing it. The GC leaves it in memory. I added an extra function to each template to try clear the fabric canvas.
Template.one.onDestroyed( function(){
rec = null;
canvas.clear();
canvas.dispose();
$(canvas.wrapperEl).remove()
})
but still seeing the memory leak continue.
The problem was resolved.
I moved the var canvas definition outside of the function blocks to the root of the file, In meteor this makes it global to the scope of the file, not a true application global. The fabricjs canvas clear() dispose() were from a recommendation by one of the authors of fabric posted as an answer to someone else's question,
I use AngularJS. I want to present an InfoBubble with dynamic content and some functions of AngularJS like ng-click, ng-mouseover. Using InfoWindows I had to compile html first and then set the compiled html as the content of the InfoWindows. Unfortunately, this is not working for InfoBubbles. When I add static html it has no problem, but when I add the compiled html it seems to have nothing as content.
var htmlElement = '<div ng-include="\'/home/include/infoBubble.html\'"></div>'
var compiled = $compile(htmlElement)($scope)
infoWindow = new InfoBubble({
content: compiled[0],
shadowStyle: 1,
padding: 0,
backgroundColor: 'rgb(57,57,57)',
borderRadius: 4,
arrowSize: 10,
borderWidth: 1,
borderColor: '#2c2c2c',
disableAutoPan: true,
hideCloseButton: true,
arrowPosition: 30,
backgroundClassName: 'phoney',
arrowStyle: 2
});
infoWindow.open(vm.map, marker);
The problem was that I had no max and min heights and widths. Setting those solved the problem.
I want to display Markers on Google map with title displayed under them as shown in picture:
Now this I read was possible in v2 using ELabel but is deprecated in v3. Is there any possible way to show some text under icons of markers in Google Maps V3?
Since at least October 2016, the official API provides a way to add permanently visible labels that are longer than one letter. See this reply by a Google project member.
var m = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
label: 'Hello world',
});
By default, the result looks like:
Pretty unreadable. Fortunately the API also allows a MarkerLabel object instead of a plain string:
var m = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
label: {
color: 'white',
fontWeight: 'bold',
text: 'Hello world',
},
});
Snippet above yields the following result:
However, the original question asked if the label could be located below the marker. The MarkerLabel docs mention this is possible with a custom icon and labelOrigin property. If we want to use the default icon, one is available at GitHub. Let us add the icon object:
var m = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
label: {
color: 'white',
fontWeight: 'bold',
text: 'Hello world',
},
icon: {
labelOrigin: new google.maps.Point(11, 50),
url: 'default_marker.png',
size: new google.maps.Size(22, 40),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(11, 40),
},
});
This results:
Pretty good! However, this whole approach has a shortcoming that the box in the original question does not have: readability with each map type. If the map type is changed from the satellite to the default the resulting label is hard to read:
An easy but not perfect way to avoid the low contrast in the both types is to set color: 'gray':
However, the gray color fails near urban areas. A better option would be to apply text-shadow CSS property to draw black linings for the white text. However, I cannot find a way to apply the property to the labels because few DOM elements created by Google Maps define a class:
The best option I came up to is to detect changes in the map type and update label color for each marker:
map.addListener('maptypeid_changed', function () {
var typeToColor, type, color, k, label;
typeToColor = {
'terrain': 'black',
'roadmap': 'black',
'hybrid': 'white',
'satellite': 'white',
};
type = map.getMapTypeId();
color = typeToColor[type];
for (k in markers) {
if (markers.hasOwnProperty(k)) {
label = markers[k].getLabel();
label.color = color;
markers[k].setLabel(label);
}
}
});
However, even this would fail on snowy or cloudy satellite imagery. I think it is still good enough in most of the cases. Nevertheless, it is nice to have the ability to display visible labels with the official API, without any plugins :)
I found the solution in an other post which worked perfectly for me.
Add numbering label to google map marker
You can't! But there's another part of maps API you can use to have permanently displayed text attached to your markers (without requiring any third party component), it's called infoWindow. Have a look at this for sample code & see it in action: https://developers.google.com/maps/documentation/javascript/examples/event-closure
If you dare using third party code, then here's something that is closer from the look & feel you want: http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/examples.html
I use the following:
MarkerWithLabel.js
( the image is just a flag.png file)
Using javascript in my X.html document
it looks something like this....
<style type="text/css">
.labels {
color: black;
background-color: white;
font-family: "Lucida Grande", "Arial", sans-serif;
font-size: 0.8em;
font-weight: bold;
text-align: center;
width: 6em;
border: 1px solid black;
white-space: normal;
}
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.9&sensor=true"></script>
<!--MarkerwithLabelClass - adjust the path!! -->
<script src="YourPathHere/markerwithlabel.js"></script>
<script type="text/javascript">
//insert standaard initializing of googlemaps here
//and other windows.onload function
window.onload = function Initialize() {
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}
function CreateMarker(lat, long, titel, label, image, anchorY, anchorX){
var latlng = new google.maps.LatLng(parseFloat(lat), parseFloat(long));//I use parseFloat cause my parameters are strings(coming from JSON-string)
var marker = new MarkerWithLabel({
zIndex: 1,
title: titel,
position: latlng,
draggable: false,
icon: image,
labelContent: label,
labelAnchor: new google.maps.Point(30, -2),
labelClass: "labels", // the CSS class for the label
labelStyle: { opacity: 0.80 }
});
return marker;
}
</script>
Read up on license info for google maps API here : https://www.google.com/intx/en_uk/work/mapsearth/products/mapsapi.html
You should be able to use the same principle as in this example. Instead of listening to the mouse events you should create a new custom control for each marker and then position it below the marker. Hope it works out.