I have been trying for days and can't get wikitude example app run. I'm new in this framework bu documentation doesn't give me a clear explanation. I'm trying this:
* Inside my head tag I have included the wikitude plugin (and of course I have put mi licence trial key), like this:
<script src="js/WikitudePlugin.js"></script>
Next, I have written the sample code:
var World = {
loaded: false,
init: function initFn() {
this.createOverlays();
},
createOverlays: function createOverlaysFn() {
this.tracker = new AR.ClientTracker("assets/magazine.wtc", {
onLoaded: this.worldLoaded
});
this.imgButton = new AR.ImageResource("assets/wwwButton.jpg");
/*
The next step is to create the augmentation. In this example an image resource is created and passed to the AR.ImageDrawable. A drawable is a visual component that can be connected to an IR target (AR.Trackable2DObject) or a geolocated object (AR.GeoObject). The AR.ImageDrawable is initialized by the image and its size. Optional parameters allow for position it relative to the recognized target.
*/
var imgOne = new AR.ImageResource("assets/imageOne.png");
var overlayOne = new AR.ImageDrawable(imgOne, 1, {
offsetX: -0.15,
offsetY: 0
});
/*
For each target an AR.ImageDrawable for the button is created by utilizing the helper function createWwwButton(url, options). The returned drawable is then added to the drawables.cam array on creation of the AR.Trackable2DObject.
*/
var pageOneButton = this.createWwwButton("http://n1sco.com/specifications/", 0.1, {
offsetX: -0.25,
offsetY: -0.25,
zOrder: 1
});
/*
This combines everything by creating an AR.Trackable2DObject with the previously created tracker, the name of the image target as defined in the target collection and the drawable that should augment the recognized image.
Note that this time a specific target name is used to create a specific augmentation for that exact target.
*/
var pageOne = new AR.Trackable2DObject(this.tracker, "pageOne", {
drawables: {
cam: [overlayOne, pageOneButton]
}
});
/*
Similar to the first part, the image resource and the AR.ImageDrawable for the second overlay are created.
*/
var imgTwo = new AR.ImageResource("assets/imageTwo.png");
var overlayTwo = new AR.ImageDrawable(imgTwo, 0.5, {
offsetX: 0.12,
offsetY: -0.01
});
var pageTwoButton = this.createWwwButton("http://goo.gl/qxck1", 0.15, {
offsetX: 0,
offsetY: -0.25,
zOrder: 1
});
/*
The AR.Trackable2DObject for the second page uses the same tracker but with a different target name and the second overlay.
*/
var pageTwo = new AR.Trackable2DObject(this.tracker, "pageTwo", {
drawables: {
cam: [overlayTwo, pageTwoButton]
}
});
},
createWwwButton: function createWwwButtonFn(url, size, options) {
/*
As the button should be clickable the onClick trigger is defined in the options passed to the AR.ImageDrawable. In general each drawable can be made clickable by defining its onClick trigger. The function assigned to the click trigger calls AR.context.openInBrowser with the specified URL, which opens the URL in the browser.
*/
options.onClick = function() {
AR.context.openInBrowser(url);
};
return new AR.ImageDrawable(this.imgButton, size, options);
},
worldLoaded: function worldLoadedFn() {
var cssDivInstructions = " style='display: table-cell;vertical-align: middle; text-align: right; width: 50%; padding-right: 15px;'";
var cssDivSurfer = " style='display: table-cell;vertical-align: middle; text-align: left; padding-right: 15px; width: 38px'";
var cssDivBiker = " style='display: table-cell;vertical-align: middle; text-align: left; padding-right: 15px;'";
document.getElementById('loadingMessage').innerHTML =
"<div" + cssDivInstructions + ">Scan Target #1 (surfer) or #2 (biker):</div>" +
"<div" + cssDivSurfer + "><img src='assets/surfer.png'></img></div>" +
"<div" + cssDivBiker + "><img src='assets/bike.png'></img></div>";
// Remove Scan target message after 10 sec.
setTimeout(function() {
var e = document.getElementById('loadingMessage');
e.parentElement.removeChild(e);
}, 10000);
}
};
World.init();
I don't know what I'm doing wrong, if I write some alert in the init functionit doesn't show anything.
Since your question requires some back and forth and isn't really suitable for the StackOverflow question/answer format. I'll suggest we move this discussion to your thread on our forums: http://www.wikitude.com/developer/developer-forum/-/message_boards/message/690051?p_p_auth=Br6dzsxQ
Related
I am new to phaser and I am trying to detect a click on several images in phaser3 .This has somehow become a two part problem for me.
First is to detect click on the objects, but even if I click anywhere else on the screen also the click handler fires.
Second part is that I have identical and multiple images on the scene, and I want to detect clicks on each of them inside a single function only and detect which image was clicked .
Here is my code:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/phaser#3.24.1/dist/phaser-arcade-physics.min.js"></script>
<style media="screen">
canvas { display : block; margin : auto;}
</style>
</head>
<body>
<script>
var config = {
type: Phaser.CANVAS,
scale: {
mode: Phaser.Scale.ScaleModes.FIT,
parent: 'phaser-example',
autoCenter: Phaser.Scale.CENTER_BOTH,
width: 400,
height: 640
},
// width: 400,
// height: 640,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 10 }
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
var game = new Phaser.Game(config);
var Bimages;
function preload ()
{
this.load.setBaseURL('http://localhost:3000');
this.load.image('sky', 'assets/skies/deepblue.png');
this.load.image('tube1', 'assets/myassets/ballSort/tube.png');
this.load.image('tube2', 'assets/myassets/ballSort/tube.png');
}
var numOfTestTubes = 5;
var storeTubes = [];
function create ()
{
ctx = this;
this.add.image(400, 300, 'sky').scaleY = 1.2;
var t1 = ctx.add.image(150, 300, 'tube1');
t1.scaleY = 0.5;
t1.scaleX = 0.5;
var t2 = ctx.add.image(220, 300, 'tube2');
t2.scaleY = 0.5;
t2.scaleX = 0.5;
t1.setInteractive();
t2.setInteractive();
t1.on('pointerdown', handleclick);
}
function update(){
}
function handleclick(pointer, targets){
console.log("clicked0",pointer);
}
</script>
</body>
</html>
Can anyone help me out here please?
The pointerdown event listener on game objects is different than the pointerdown event listener on the global input manager. If you instead do this.input.on('pointerdown', ...) you'll get a callback with the pointer, but also an array of game objects that were clicked, with an empty array if no game objects were clicked. If you need to register clicks on input objects that overlap each other, you can change this behavior with #setTopOnly. You can check object equality or against some property expected such as the object's name or texture key. I linked a stackblitz with rectangles, but understand they are behaving the same as an image's hitbox would.
https://stackblitz.com/edit/phaser-so-global-input-manager?file=index.ts
I am using the Raphael plugin for the first time and so far I managed to create a map of Germany and to outline all different regions inside. I found out how to bind mouse-over effects, so when I hover over a region its color changes. Everything looks fine until the moment when I want to trigger the same mouse-over effect from outside the map. There is a list of links to all the regions and each link should color its respective geographical position (path) on the map when hovered. The problem is that I don't know how to trigger the mouse-over effect from outside.
This is the reference guide I used for my code: Clickable France regions map
This is my map initialization:
var regions = [];
var style = {
fill: "#f2f2f2",
stroke: "#aaaaaa",
"stroke-width": 1,
"stroke-linejoin": "round",
cursor: "pointer",
class: "svgclass"
};
var animationSpeed = 500;
var hoverStyle = {
fill: "#dddddd"
}
var map = Raphael("svggroup", "100%", "auto");
map.setViewBox(0, 0, 585.5141, 792.66785, true);
// declaration of all regions (states)
....
var bayern = map.path("M266.49486,..,483.2201999999994Z");
bayern.attr(style).data({ 'href': '/bayern', 'id': 'bayern', 'name': 'Bayern' }).node.setAttribute('data-id', 'bayern');
regions.push(bayern);
This is where my "normal" mouse effects take place:
for (var regionName in regions) {
(function (region) {
region[0].addEventListener("mouseover", function () {
if (region.data('href')) {
region.animate(hoverStyle, animationSpeed);
}
}, true);
region[0].addEventListener("mouseout", function () {
if (region.data('href')) {
region.animate(style, animationSpeed);
}
}, true);
region[0].addEventListener("click", function () {
var url = region.data('href');
if (url){
location.href = url;
}
}, true);
})(regions[regionName]);
}
I have a menu with links and I want to bind each of them to the respective region, so that I can apply the animations, too.
$("ul.menu__navigation li a").on("mouseenter", function (e) {
// this function displays my pop-ups
showLandName($(this).data("id"));
// $(this).data("id") returns the correct ID of the region
});
I would appreciate any ideas! Thanks in advance!
I figured out a way to do it. It surely isn't the most optimal one, especially in terms of performance, but at least it gave me the desired output. I would still value a better answer, but as of right now a new loop inside the mouse-over event does the job.
$("ul.menu__navigation li a").on("mouseenter", function (e) {
// this function displays my pop-ups
showLandName($(this).data("id"));
// animate only the one hovered on the link list
var test = '/' + $(this).data("id");
for (var regionName in regions) {
(function (region) {
if (region.data('href') === test) {
region.animate(hoverStyle, animationSpeed);
}
})(regions[regionName]);
}
});
edit 2016, Oct 24
I've an idea about this feature by using 'pattern' which seems to be a good idea.
I tried to prove my thoughts with this pen, its still buggy but at least we can set the image(pattern) position and keep the original image when double click.
I'am not very good at javascript, So if you are interest in this please help to make this more useable, any discussions/thoughts or code correction is welcome.
http://codepen.io/wushan/pen/LRrQEL?editors=1010
// Create Canvas
var canvas = this.__canvas = new fabric.CanvasEx('c', {
preserveObjectStacking: true
});
fabric.Object.prototype.transparentCorners = false;
// Global Settings
var url = "http://fabricjs.com/assets/pug.jpg";
//Make the Pattern by url
function createMaskedImage(url) {
//Load Image
fabric.Image.fromURL(url, function(img) {
img.scaleToWidth(300);
//Make a Pattern
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(img);
var pattern = new fabric.Pattern({
source: function() {
patternSourceCanvas.setDimensions({
width: img.getWidth(),
height: img.getHeight()
});
return patternSourceCanvas.getElement();
},
repeat: 'no-repeat'
});
console.log(pattern.offsetX)
console.log(pattern.offsetY)
console.log(img.getWidth()) // 縮小後 (*scale)
console.log(img.width) // 原尺寸
//Mask (can be any shape ex: Polygon, Circles....)
var rect = new fabric.Rect({
width: 200,
height: 200,
left: 150,
top: 100,
fill: pattern
})
//Bind Double Click Event from fabric.ext
//https://github.com/mazong1123/fabric.ext
rect.on('object:dblclick', function (options) {
//Pass pattern out
enterEditMode(rect, img);
});
canvas.add(rect);
canvas.setActiveObject(rect);
});
}
function enterEditMode(mask, image) {
image.left = mask.left;
image.top = mask.top;
// New Image
// Fake Crop Area (fixed)
var rect = new fabric.Rect({
width: mask.width,
height: mask.height,
left: mask.left,
top: mask.top,
fill: '#000000',
opacity: 0.8,
selectable: false
})
canvas.remove(mask);
canvas.add(image);
image.on('object:dblclick', function (options) {
//Flatten
flatten(rect, image);
});
canvas.add(rect);
// console.log(JSON.stringify(canvas));
}
function flatten(mask, image) {
//Make a Pattern
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(image);
var pattern = new fabric.Pattern({
source: function() {
patternSourceCanvas.setDimensions({
width: image.getWidth(),
height: image.getHeight()
});
return patternSourceCanvas.getElement();
},
repeat: 'no-repeat'
});
//Offsets
pattern.offsetX = image.left - mask.left - image.left;
pattern.offsetY = image.top - mask.top - image.top;
var rect = new fabric.Rect({
width: mask.width,
height: mask.height,
left: mask.left,
top: mask.top,
fill: pattern
})
//Bind Double Click Event from fabric.ext
//https://github.com/mazong1123/fabric.ext
rect.on('object:dblclick', function (options) {
//Pass pattern out
enterEditMode(rect, image);
});
canvas.remove(mask);
canvas.remove(image);
canvas.add(rect);
canvas.setActiveObject(rect);
canvas.renderAll();
}
//Button Events
//Create
document.getElementById('createMaskedImage').addEventListener('click', function () {
createMaskedImage(url);
});
Test this :
click 'create'
double click on the image object
move/scale the image
double click the image to flatten the obejct.
Know issue:
when cutting the image without scale, the image position looks correct but there is a wired transparent space.
It generates a lot duplicate objects on the scene...
Original Post
I've been working with fabric.js for a few month, haven't seen any example or discussions about a mask/crop system which is behaves like canva.com ( which is way easy to understand for users. )
the object looks like this:
when double clicked on a group/mask, it shows the original image with an unselectable mask, you can move/scale the image whatever you need and click 'OK' to made the change without modifying the original image.
I'd like to know if there is any possible solutions about making this in fabricjs, or maybe some thoughts about this issue is welcome.
Thank you a lot !
I am trying to display the mouse cursors of all the connected client screen on every client's screen. Something like this : http://www.moock.org/unity/clients/uCoop/uCoop.html
I am working on socket.io using node.js.
I tried drawing a circle on the cursor position on the screen using context.drawImage on mousemove but the cursor remains on the screen even after the mouse moves away and clearing the screen makes it slow. So I think, drawing on a canvas is not a perfect solution, I just need to emit the information of mouse co-ordinates to the client somehow. But I don't know how.
Client side code snippet:
socket.on('draw_cursor', function (data) {
var line = data.line;
context.beginPath();
context.fillStyle = "#000000";
context.arc(line[0].x*width, line[0].y*height, 10, 0, 2*Math.PI);
context.fill();
delay(2000);
});
function mainLoop() {
if (mouse.move && mouse.pos_prev) {
// send line to to the server
socket.emit('draw_cursor', { line: [ mouse.pos, mouse.pos_prev ] });
}
}
Server side code snippet:
socket.on('draw_cursor', function (data) {
io.emit('draw_cursor', { line: data.line });
});
Thanks
Vinni
I propose you draw HTML elements instead of using a canvas. That way, you can reuse the same element for each cursor and just update the coordinates. To do this, you should add an ID to each draw_cursor message, to keep track of which element is which:
socket.on('draw_cursor', function (data) {
io.emit('draw_cursor', { line: data.line, id: socket.id });
});
Then, in your client handler, you find or create the HTML element and update it's position:
function getCursorElement (id) {
var elementId = 'cursor-' + id;
var element = document.getElementById(elementId);
if(element == null) {
element = document.createElement('div');
element.id = elementId;
element.className = 'cursor';
// Perhaps you want to attach these elements another parent than document
document.appendChild(element);
}
return element;
}
socket.on('draw_cursor', function (data) {
var el = getCursorElement(data.id);
el.style.x = data.line[0].x;
el.style.y = data.line[0].y;
}
Now, you just have to style the cursor elements. Here's a little css to start with:
.cursor {
position: absolute;
background: black;
width: 20px;
height: 20px;
border-radius: 10px;
}
I have an HTML5 canvas that is displaying a number of images and four description boxes. It is currently possible to drag and drop the images around the canvas, but I want to add functionality to remove an image when it is dragged to its correct description box.
I've tried writing the following function, but it does not currently seem to be doing anything... i.e. if I drag an image to its description box and drop it, it still remains on the canvas:
function initStage(images){
var stage = new Kinetic.Stage({
container: "container",
width: 1000,
height: 500
});
var descriptionLayer = new Kinetic.Layer();
//var imagesLayer = new Kinetic.Layer();
var allImages = [];
var currentScore = 0;
var descriptionBoxes = {
assetsDescriptionBox: {
x: 70,
y: 400
},
liabilitiesDescriptionBox: {
x: 300,
y: 400
},
incomeDescriptionBox: {
x: 530,
y: 400
},
expenditureDescriptionBox: {
x: 760,
y: 400
},
};
/*Code to detect whether image has been dragged to correct description box */
for (var key in sources){
/*Anonymous function to induce scope */
(function(){
var privateKey = key;
var imageSource = sources[key];
/*Check if image has been dragged to the correct box, and add it to that box's
array and remove from canvas if it has */
canvasImage.on("dragend", function(){
var descriptionBox = descriptionBoxes[privateKey];
if(!canvasImage.inRightPlace && isNearDescriptionBox(itemImage, descriptionBox)){
context.remove(canvasImage);
/*Will need to add a line in here to add the image to the box's array */
}
})
})();
}
}
The code I've written is based on the tutorial that I found at: http://www.html5canvastutorials.com/labs/html5-canvas-animals-on-the-beach-game-with-kineticjs/
Can anyone spot what I'm doing wrong, and how I can ensure that the image is removed from the canvas when it's dragged to its corresponding description box?
That example bugged me because it seemed old, so I edited it a little...
http://jsfiddle.net/LTq9C/1/
...keep in mind that I cant be positive that all my edits are the best way to do things, Im new and all ;)
And here I've edited it again for you to show the image being removed...
animal.on("dragend", function() {
var outline = outlines[privKey + "_black"];
if (!animal.inRightPlace && isNearOutline(animal, outline)) {
animal.remove();
animalLayer.draw();
}
});
http://jsfiddle.net/8S3Qq/1/