976 lines
30 KiB
JavaScript
976 lines
30 KiB
JavaScript
/**
|
|
* a 2d Canvas renderer for fast rendering
|
|
* Created by gaimeng on 15/2/2.
|
|
*/
|
|
|
|
//---------------------IndoorMap2D class-----------------
|
|
IndoorMap2d = function(mapdiv){
|
|
var _this = this;
|
|
var _mapDiv = mapdiv;
|
|
var _controls;
|
|
|
|
var _curFloorId = 0;
|
|
var _selectionListener = null;
|
|
var _selected, _selectedOldColor;
|
|
var _theme = null;
|
|
|
|
this.options = {
|
|
showNames : true,
|
|
showPubPoints : true,
|
|
selectable : true,
|
|
movable: true
|
|
}
|
|
this.containerSize = [0, 0];
|
|
this.containerHalfSize = [0, 0];
|
|
this.containerPos = [0,0];
|
|
this.mapCenter = [0 ,0];
|
|
|
|
this.renderer = null;
|
|
this.is3d = false;
|
|
|
|
//var _marker;
|
|
|
|
this.init = function(){
|
|
_this.containerSize[0] = parseInt(_mapDiv.style.width);
|
|
_this.containerSize[1] = parseInt(_mapDiv.style.height);
|
|
_this.containerHalfSize[0] = _this.containerSize[0] / 2;
|
|
_this.containerHalfSize[1] = _this.containerSize[1] / 2;
|
|
_this.containerPos = IDM.DomUtil.getPos(_mapDiv);
|
|
|
|
_this.renderer = new Canvas2DRenderer(_this);
|
|
var canvasDiv = _this.renderer.domElement;
|
|
_controls = new Controller2D(_this.renderer);
|
|
_mapDiv.appendChild(canvasDiv);
|
|
_mapDiv.style.overflow = "hidden";
|
|
|
|
|
|
}
|
|
|
|
this.reset = function(){
|
|
_controls.reset();
|
|
_this.renderer.reset();
|
|
}
|
|
|
|
this.setTheme = function(theme){
|
|
if(_theme == null){
|
|
_theme = theme
|
|
} else if(_theme != theme) {
|
|
_theme = theme;
|
|
_this.parse(_this.mall.jsonData); //parse
|
|
redraw();
|
|
}
|
|
return _this;
|
|
}
|
|
|
|
this.theme = function(){
|
|
return _theme;
|
|
}
|
|
|
|
this.getMall = function(){
|
|
return _this.mall;
|
|
}
|
|
|
|
//load the map by the json file name
|
|
this.load = function (fileName, callback) {
|
|
_this.reset();
|
|
_theme = default2dTheme;
|
|
var loader = new IndoorMapLoader(false);
|
|
loader.load(fileName, function(mall){
|
|
_this.mall = mall;
|
|
_this.showFloor(_this.mall.getDefaultFloorId());
|
|
if(callback) {
|
|
callback();
|
|
}
|
|
|
|
|
|
});
|
|
}
|
|
|
|
this.parse = function(json){
|
|
_this.reset();
|
|
if(_theme == null) {
|
|
_theme = default2dTheme;
|
|
}
|
|
_this.mall = ParseModel(json, _this.is3d, _theme);
|
|
_this.showFloor(_this.mall.getDefaultFloorId());
|
|
|
|
_mapDiv.style.background = _theme.background;
|
|
return _this;
|
|
}
|
|
|
|
//reset the camera to default configuration
|
|
this.setDefaultView = function () {
|
|
_this.renderer.setDefaultView(_this.mall.getCurFloor());
|
|
|
|
_controls.reset();
|
|
_controls.viewChanged = true;
|
|
}
|
|
|
|
//TODO:adjust camera to fit the building
|
|
this.adjustCamera = function() {
|
|
_this.setDefaultView();
|
|
|
|
}
|
|
|
|
this.translate = function(vec){
|
|
_this.renderer.translate(vec);
|
|
}
|
|
|
|
this.zoomIn = function(zoomScale){
|
|
if(zoomScale === undefined){
|
|
zoomScale = 1.25;
|
|
}
|
|
_this.renderer.scale(zoomScale);
|
|
}
|
|
|
|
this.zoomOut = function(zoomScale){
|
|
if(zoomScale === undefined){
|
|
zoomScale = 0.8;
|
|
}
|
|
_this.renderer.scale(zoomScale);
|
|
}
|
|
|
|
this.showAreaNames = function(show) {
|
|
_this.options.showNames = show == undefined ? true : show;
|
|
redraw();
|
|
return _this;
|
|
}
|
|
|
|
//show pubPoints(entries, ATM, escalator...)
|
|
this.showPubPoints = function(show){
|
|
_this.options.showPubPoints = show == undefined ? true: show;
|
|
redraw();
|
|
return _this;
|
|
}
|
|
|
|
//get the selected object
|
|
this.getSelectedId = function(){
|
|
var id;
|
|
if(_selected && _selected.BrandShop) {
|
|
id = _selected.BrandShop;
|
|
}else{
|
|
id = -1;
|
|
}
|
|
return id;
|
|
}
|
|
|
|
//the callback function when sth is selected
|
|
this.setSelectionListener = function(callback){
|
|
_selectionListener = callback;
|
|
return _this;
|
|
}
|
|
|
|
//select object by id
|
|
this.selectById = function(id){
|
|
var floor = _this.mall.getCurFloor();
|
|
for(var i = 0; i < floor.FuncAreas.length; i++){
|
|
if(floor.FuncAreas[i].BrandShop && floor.FuncAreas[i].BrandShop == id) {
|
|
_this.deselectAll();
|
|
_this.select(floor.FuncAreas[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
//show floor by id
|
|
this.showFloor = function(floorid) {
|
|
if(_this.mall == null){
|
|
return;
|
|
}
|
|
_curFloorId = floorid;
|
|
_this.mall.showFloor(floorid);
|
|
|
|
if(_this.options.showNames) {
|
|
_this.renderer.createNameTexts(floorid, _this.mall);
|
|
}
|
|
|
|
if(_this.options.showPubPoints) {
|
|
_this.renderer.loadSpirtes(_this.mall);
|
|
}
|
|
|
|
_this.adjustCamera();
|
|
|
|
return _this;
|
|
}
|
|
|
|
// this.setSelectionMarker = function(marker){
|
|
// //_marker = marker;
|
|
// }
|
|
|
|
//set if the objects are selectable
|
|
this.setSelectable = function (selectable) {
|
|
if(selectable){
|
|
_mapDiv.addEventListener('mouseup', onSelectObject, false);
|
|
_mapDiv.addEventListener('touchend', onSelectObject, false);
|
|
}else{
|
|
_mapDiv.removeEventListener('mouseup', onSelectObject, false);
|
|
_mapDiv.removeEventListener('touchend', onSelectObject, false);
|
|
}
|
|
return _this;
|
|
}
|
|
|
|
//set if the user can pan the camera
|
|
this.setMovable = function(movable){
|
|
_controls.enable = movable;
|
|
return _this;
|
|
}
|
|
|
|
//focus
|
|
this.focus = function (obj){
|
|
_this.renderer.focus(obj);
|
|
}
|
|
|
|
this.deselectAll = function(){
|
|
if (_selected) {
|
|
_selected.fillColor = _selectedOldColor;
|
|
redraw();
|
|
}
|
|
}
|
|
|
|
//select object(just hight light it)
|
|
this.select = function(obj){
|
|
if(obj != undefined) {
|
|
//_this.focus(obj);
|
|
_selectedOldColor = obj.fillColor;
|
|
obj.fillColor = _theme.selected;
|
|
//var pos = _this.renderer.localToWorld(obj.Center);
|
|
_selected = obj;
|
|
redraw();
|
|
|
|
// _marker.style.left = pos[0] - _marker.width / 2;
|
|
// _marker.style.top = pos[1] - _marker.height / 2;
|
|
// _marker.style.visibility = true;
|
|
}
|
|
}
|
|
|
|
function onSelectObject(event){
|
|
event.preventDefault();
|
|
var pos = [0,0]
|
|
if(event.type == "touchend"){
|
|
pos[0] = event.changedTouches[0].clientX;
|
|
pos[1] = event.changedTouches[0].clientY;
|
|
}else {
|
|
pos[0] = event.clientX;
|
|
pos[1] = event.clientY;
|
|
}
|
|
|
|
if(Math.abs(pos[0] - _controls.startPoint[0] + pos[1] - _controls.startPoint[1]) <5) {
|
|
//turn browser point into container viewport point
|
|
pos[0] -= IDM.DomUtil.getElementLeft(_mapDiv);
|
|
pos[1] -= IDM.DomUtil.getElementTop(_mapDiv);
|
|
|
|
//deselect the old one
|
|
_this.deselectAll();
|
|
|
|
_selected = _this.renderer.onSelect(pos);
|
|
|
|
if (_selected) {
|
|
_this.select(_selected)
|
|
console.log(_this.getSelectedId());
|
|
if (_selectionListener) {
|
|
_selectionListener(_this.getSelectedId());
|
|
}
|
|
|
|
} else {
|
|
if (_selectionListener) {
|
|
_selectionListener(-1);
|
|
}
|
|
}
|
|
|
|
}
|
|
redraw();
|
|
}
|
|
|
|
function redraw(){
|
|
_this.renderer.clearBg();
|
|
_this.renderer.render(_this.mall);
|
|
}
|
|
|
|
function animate () {
|
|
requestAnimationFrame(animate);
|
|
//_controls.update();
|
|
if(_controls.viewChanged) {
|
|
_this.renderer.render(_this.mall);
|
|
_controls.viewChanged = false;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
_this.init();
|
|
animate();
|
|
}
|
|
|
|
//---------------------the Sprite class------------------
|
|
function CanvasSprite(params){
|
|
var _this = this,
|
|
_ctx = params.ctx,
|
|
_width = params.width,
|
|
_height = params.height,
|
|
_offsetX = 0,
|
|
_offsetY = 0,
|
|
_visible = true,
|
|
|
|
_img = new Image();
|
|
_img.src = params.image;
|
|
|
|
this.draw = function(x, y){
|
|
if(_visible){
|
|
_ctx.drawImage(_img,_offsetX, _offsetY, _width, _height, x >> 0, y >> 0, _width, _height);
|
|
}
|
|
}
|
|
|
|
this.show = function(){
|
|
_visible = true;
|
|
}
|
|
|
|
this.hide = function(){
|
|
_visible = false;
|
|
}
|
|
}
|
|
|
|
Canvas2DRenderer = function (map) {
|
|
|
|
var _this = this,
|
|
_map = map,
|
|
_ctx;
|
|
var _canvas = document.createElement('canvas');
|
|
|
|
var _padding = 0.2; //padding between map bounding box and the div boundary
|
|
|
|
var _floorSize = [0, 0];
|
|
|
|
//canvas real size
|
|
var _canvasPos = [0, 0], //in the browser coordinate
|
|
_canvasSize = [0, 0],
|
|
_canvasHalfSize = [0, 0],
|
|
_bounds = null,
|
|
|
|
_nameTexts = [],
|
|
_sprites = [],
|
|
_pubPoints = [0,0],
|
|
|
|
|
|
_scale = 1.0;
|
|
var _curFloor = null;
|
|
var _objSize = [0,0];
|
|
var _translate = [0,0];
|
|
|
|
this.domElement = _canvas;
|
|
this.mapCenter = [];
|
|
var _devicePixelRatio = 1;
|
|
|
|
function _init(){
|
|
_canvas.style.position = "absolute";
|
|
_ctx = _canvas.getContext('2d');
|
|
_this.updateViewport();
|
|
|
|
|
|
}
|
|
|
|
this.updateViewport = function(isZoom){
|
|
var clippadding = clipPadding();
|
|
var clipSize = [(_map.containerSize[0]*clippadding) >> 0, (_map.containerSize[1]*clippadding) >> 0];
|
|
_canvasPos[0] = _map.containerPos[0] - clipSize[0];
|
|
_canvasPos[1] = _map.containerPos[1] - clipSize[1];
|
|
var realRatio = 1 + 2*clippadding;
|
|
_canvasSize[0] = (realRatio * _map.containerSize[0]) >> 0;
|
|
_canvasSize[1] = (realRatio * _map.containerSize[1]) >> 0;
|
|
_canvasHalfSize[0] = _canvasSize[0]*.5;
|
|
_canvasHalfSize[1] = _canvasSize[1]*.5;
|
|
_bounds = new Rect(-_canvasHalfSize[0],-_canvasHalfSize[1],_canvasHalfSize[0], _canvasHalfSize[1]);
|
|
_canvasPos[0] = -clipSize[0]
|
|
_canvasPos[1] = -clipSize[1]
|
|
IDM.DomUtil.setPos(_canvas, _canvasPos);
|
|
_devicePixelRatio = window.devicePixelRatio || 1;
|
|
var area = _canvasSize[0]*_canvasSize[1]*_devicePixelRatio*_devicePixelRatio;
|
|
_devicePixelRatio = (IDM.Browser.mobile && !IDM.Browser.android || IDM.Browser.android23) && (area > 5E6) ? 1 : _devicePixelRatio;
|
|
_canvas.width = _canvasSize[0] * _devicePixelRatio;
|
|
_canvas.height = _canvasSize[1] * _devicePixelRatio;
|
|
_canvas.style.width = _canvasSize[0] + "px";
|
|
_canvas.style.height = _canvasSize[1] + "px";
|
|
_ctx.scale(_devicePixelRatio, _devicePixelRatio);
|
|
_ctx.translate(_canvasHalfSize[0], _canvasHalfSize[1]);
|
|
if(isZoom){
|
|
_ctx.translate(_translate[0],_translate[1]);
|
|
}
|
|
}
|
|
|
|
function clipPadding(){
|
|
var ratio = ((IDM.Browser.mobile ? 1280 : 2000) / Math.max(window.innerWidth, window.innerHeight) - 1) / 2;
|
|
return Math.max(0, Math.min(.5, ratio));
|
|
}
|
|
|
|
this.translate = function(vec){
|
|
//TODO: clip polygons if necessary
|
|
|
|
_translate[0] += vec[0];
|
|
_translate[1] += vec[1];
|
|
_ctx.translate(_translate[0], _translate[1]);
|
|
_this.clearBg();
|
|
_this.render();
|
|
}
|
|
|
|
this.scale = function(scale){
|
|
_scale *= scale;
|
|
_curFloor = _map.mall.getCurFloor();
|
|
updateOutline(_curFloor, _scale);
|
|
var funcAreas = _curFloor.FuncAreas;
|
|
for(var i = 0; i < funcAreas.length; i++){
|
|
updateOutline(funcAreas[i], _scale);
|
|
}
|
|
var pubPoints = _curFloor.PubPoint;
|
|
for(var i = 0; i < pubPoints.length ; i++){
|
|
updateOutline(pubPoints[i], _scale);
|
|
}
|
|
_ctx.translate(-_translate[0], -_translate[1]);
|
|
_translate[0] *= scale;
|
|
_translate[1] *= scale;
|
|
_ctx.translate(_translate[0], _translate[1]);
|
|
_this.clearBg();
|
|
_this.render();
|
|
}
|
|
function updateOutline(obj, scale){
|
|
var outline = obj.Outline[0][0];
|
|
obj.newOutline = [];
|
|
for(var i = 0; i < outline.length - 1; i+=2){
|
|
var newPoint = updatePoint([outline[i], outline[i+1]], scale);
|
|
obj.newOutline.push(newPoint[0]);
|
|
obj.newOutline.push(newPoint[1]);
|
|
}
|
|
obj.rect = IDM.GeomUtil.getBoundingRect(obj.newOutline);
|
|
//if(!obj.rect.isCollide(_bounds)){
|
|
// obj.newOutline = [];
|
|
// obj.rect = new Rect();
|
|
//}
|
|
if(obj.Center) {
|
|
obj.Center = [((obj.rect.br[0]+obj.rect.tl[0])/2) >> 0 , ((obj.rect.br[1]+obj.rect.tl[1])/2) >> 0];
|
|
}
|
|
}
|
|
|
|
function updatePoint(point, scale){
|
|
return [((point[0] - _this.mapCenter[0])*scale)>>0, ((point[1] - _this.mapCenter[1])*scale)>>0];
|
|
}
|
|
|
|
this.setDefaultView = function (floor) {
|
|
floor.rect = IDM.GeomUtil.getBoundingRect(floor.Outline[0][0]);
|
|
|
|
var floorSize = [0, 0];
|
|
floorSize[0] = floor.rect.br[0] - floor.rect.tl[0];
|
|
floorSize[1] = floor.rect.br[1] - floor.rect.tl[1];
|
|
var scaleX = (_map.containerSize[0]*(1 - _padding)) / floorSize[0];
|
|
var scaleY = (_map.containerSize[1]*(1 - _padding)) / floorSize[1];
|
|
|
|
|
|
_this.mapCenter[0] = (floor.rect.br[0] + floor.rect.tl[0]) / 2;
|
|
_this.mapCenter[1] = (floor.rect.br[1] + floor.rect.tl[1]) / 2;
|
|
|
|
_ctx.translate(-_translate[0], -_translate[1]);
|
|
_scale = 1.0;
|
|
_translate = [0, 0];
|
|
_this.scale(Math.min(scaleX , scaleY));
|
|
}
|
|
|
|
this.reset = function(){
|
|
_nameTexts.length = 0;
|
|
|
|
|
|
}
|
|
|
|
this.focus = function (object) {
|
|
//if(object._id != _oldId) {
|
|
|
|
var width = object.rect.br[0] - object.rect.tl[0];
|
|
var height = object.rect.br[1] - object.rect.tl[1];
|
|
var floor = _map.getMall().getCurFloor();
|
|
var floorSize = [0, 0];
|
|
floorSize[0] = floor.rect.br[0] - floor.rect.tl[0];
|
|
floorSize[1] = floor.rect.br[1] - floor.rect.tl[1];
|
|
var ratio = (width+height) / (floorSize[0]+floorSize[1]);
|
|
//var padding = ratio > 0.005? _mapWidth * 0.5 : _mapWidth * 0.85;
|
|
|
|
|
|
var minSize = Math.min(_map.containerSize[0], _map.containerSize[1]);
|
|
var padding = (-1.42*ratio + 0.9) * minSize; //empirical value
|
|
minSize /= 2;
|
|
padding < minSize? padding = minSize : padding;
|
|
var scaleX = (_map.containerSize[0] - padding) / width;
|
|
var scaleY = (_map.containerSize[1] - padding) / height;
|
|
_objSize[0] = width;
|
|
_objSize[1] = height;
|
|
var tmpScale = scaleX < scaleY ? scaleX : scaleY;
|
|
_this.scale(tmpScale);
|
|
|
|
var center = [];
|
|
center[0] = (object.rect.br[0] + object.rect.tl[0]) / 2;
|
|
center[1] = - (object.rect.br[1] + object.rect.tl[1]) / 2;
|
|
var curCenter = _this.worldToLocal([_map.containerHalfSize[0], _map.containerHalfSize[1]]);
|
|
var vec = [curCenter[0]-center[0], curCenter[1]-center[1]];
|
|
_this.updateViewport();
|
|
_this.translate(vec);
|
|
}
|
|
|
|
this.screenShot = function(type){
|
|
var tmpCanvas = document.createElement("canvas");
|
|
tmpCanvas.width = _map.containerSize[0], tmpCanvas.height = _map.containerSize[1];
|
|
|
|
var tmpCtx = tmpCanvas.getContext('2d');
|
|
tmpCtx.drawImage(_canvas,_canvasPos[0],_canvasPos[1]);
|
|
return tmpCanvas.toDataURL(type);
|
|
}
|
|
|
|
this.render = function (){
|
|
if(_map.mall === undefined) {
|
|
return;
|
|
}
|
|
|
|
var theme = _map.theme();
|
|
|
|
//get render data
|
|
_curFloor = _map.mall.getCurFloor();
|
|
|
|
_ctx.save();
|
|
|
|
//draw floor
|
|
var poly = _curFloor.newOutline;
|
|
_ctx.beginPath();
|
|
_ctx.moveTo(poly[0], -poly[1]);
|
|
for(var i = 2; i < poly.length - 1; i+=2){
|
|
_ctx.lineTo(poly[i],-poly[i+1]);
|
|
}
|
|
_ctx.closePath();
|
|
|
|
_ctx.fillStyle = _curFloor.fillColor;
|
|
_ctx.fill();
|
|
_ctx.strokeStyle = theme.strokeStyle.color;
|
|
_ctx.lineWidth = theme.strokeStyle.linewidth;
|
|
_ctx.stroke();
|
|
|
|
//draw funcAreas
|
|
var funcAreas = _curFloor.FuncAreas;
|
|
for(var i = 0 ; i < funcAreas.length; i++){
|
|
var funcArea = funcAreas[i];
|
|
var poly = funcArea.newOutline;
|
|
if(poly.length < 6){ //less than 3 points, return
|
|
continue;
|
|
}
|
|
_ctx.beginPath();
|
|
|
|
_ctx.moveTo(poly[0], -poly[1]);
|
|
for(var j = 2; j < poly.length - 1; j+=2){
|
|
_ctx.lineTo(poly[j],-poly[j+1]);
|
|
}
|
|
_ctx.closePath();
|
|
|
|
_ctx.fillStyle = funcArea.fillColor;
|
|
_ctx.fill();
|
|
_ctx.stroke();
|
|
}
|
|
|
|
////test for selection
|
|
//_ctx.fillStyle="#FF0000";
|
|
//_ctx.beginPath();
|
|
//_ctx.arc(_pubPoints[0],_pubPoints[1],5,0,Math.PI*2,true);
|
|
//_ctx.closePath();
|
|
//_ctx.fill();
|
|
|
|
_ctx.restore();
|
|
|
|
var options = _map.options;
|
|
if(options.showNames){
|
|
var fontStyle = theme.fontStyle;
|
|
//_ctx.textAlign = fontStyle.textAlign;
|
|
_ctx.textBaseline = fontStyle.textBaseline;
|
|
_ctx.fillStyle = theme.fontStyle.color;
|
|
_ctx.font = fontStyle.fontsize + "px/1.4 " + fontStyle.fontface;
|
|
var textRects = [];
|
|
for(var i = 0 ; i < funcAreas.length; i++){
|
|
var nameText = _nameTexts[i];
|
|
|
|
var center = funcAreas[i].Center;
|
|
|
|
var rect = new Rect(center[0] - nameText.halfWidth, -center[1] - nameText.halfHeight, center[0] + nameText.halfWidth, -center[1] + nameText.halfHeight);
|
|
textRects.push(rect);
|
|
|
|
nameText.visible = true;
|
|
|
|
//for(var j = 0; j < i; j++){
|
|
// if(_nameTexts[j].visible && textRects[j].isCollide(rect)){
|
|
// nameText.visible = false;
|
|
// break;
|
|
// }
|
|
//}
|
|
if((funcAreas[i].rect.br[0]-funcAreas[i].rect.tl[0])*0.9 < nameText.halfWidth*2)
|
|
nameText.visible = false;
|
|
if(nameText.visible) {
|
|
_ctx.fillText(nameText.text, (center[0] - nameText.halfWidth) >> 0, (-center[1]) >> 0);
|
|
// _ctx.beginPath();
|
|
// _ctx.arc(center[0], center[1], 3, 0, Math.PI * 2, true);
|
|
// _ctx.closePath();
|
|
//
|
|
// _ctx.fill();
|
|
// _ctx.strokeRect(rect.tl[0], rect.tl[1], rect.br[0] - rect.tl[0], rect.br[1] - rect.tl[1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(options.showPubPoints){
|
|
var pubPoints = _curFloor.PubPoint;
|
|
var imgWidth = 20 , imgHeight = 20 ;
|
|
// if(_scale < 0.1){
|
|
// imgWidth = imgHeight = 12;
|
|
// }
|
|
|
|
var imgWidthHalf = imgWidth/2, imgHeightHalf = imgHeight/2;
|
|
var pubPointRects = [];
|
|
for(var i = 0; i < pubPoints.length; i++){
|
|
var pubPoint = pubPoints[i];
|
|
var center = pubPoint.newOutline;
|
|
var rect = new Rect(center[0] - imgWidthHalf, -center[1] - imgHeightHalf, center[0] + imgWidthHalf, -center[1] + imgHeightHalf);
|
|
pubPointRects.push(rect);
|
|
|
|
pubPoint.visible = true;
|
|
for(var j = 0; j < i; j++){
|
|
if(pubPoints[j].visible && pubPointRects[j].isCollide(rect)){
|
|
pubPoint.visible = false;
|
|
break;
|
|
}
|
|
}
|
|
if(pubPoint.visible) {
|
|
var image = _sprites[pubPoints[i].Type];
|
|
if (image !== undefined) {
|
|
_ctx.drawImage(image, (center[0] - imgWidthHalf) >> 0, (-center[1] - imgHeightHalf) >> 0, imgWidth, imgHeight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//map the coordinate in the map to the viewport
|
|
//!!hasnt been tested yet
|
|
this.localToWorld = function(pt){
|
|
var worldPoint = [0,0];
|
|
worldPoint[0] = pt[0]+_translate[0]+_map.containerHalfSize[0] >> 0;
|
|
worldPoint[1] = pt[1]+_translate[1]+_map.containerHalfSize[1] >> 0;
|
|
return worldPoint;
|
|
}
|
|
|
|
//map the coordinate in the viewport to the map (with -y)
|
|
this.worldToLocal = function(pt){
|
|
var localPoint = [0,0];
|
|
localPoint[0] = (pt[0]-_translate[0]-_map.containerHalfSize[0]) >> 0;
|
|
localPoint[1] = (pt[1]-_translate[1]-_map.containerHalfSize[1]) >> 0;
|
|
return localPoint;
|
|
}
|
|
|
|
this.onSelect = function(point){
|
|
var tmpPos = _this.worldToLocal(point);
|
|
//_pubPoints = tmpPos;
|
|
return hitTest(tmpPos);
|
|
}
|
|
|
|
this.setSize = function(width, height) {
|
|
_canvas.style.width = width + "px";
|
|
_canvas.style.height = height + "px";
|
|
_canvasSize[0] = width * _devicePixelRatio;
|
|
_canvasSize[1] = height * _devicePixelRatio;
|
|
_canvas.width = _canvasSize[0];
|
|
_canvas.height = _canvasSize[1];
|
|
_canvasHalfSize[0] = Math.floor(width / 2);
|
|
_canvasHalfSize[1] = Math.floor(height / 2);
|
|
_ctx.scale(_devicePixelRatio, _devicePixelRatio);
|
|
}
|
|
|
|
function exceed(scale){
|
|
//var curWidth = _objSize[0] * scale;
|
|
//var curHeight = _objSize[1] * scale;
|
|
//var maxSize = MAX_CANVAS_SIZE * _devicePixelRatio;
|
|
//if(curWidth > maxSize || curHeight > maxSize){
|
|
// return true;
|
|
//}else{
|
|
// return false;
|
|
//}
|
|
return false;
|
|
}
|
|
|
|
this.clearBg = function(){
|
|
//clear background
|
|
_ctx.save();
|
|
_ctx.setTransform(1,0,0,1,0,0);
|
|
_ctx.fillStyle = _map.theme().background;
|
|
_ctx.fillRect(0,0,_canvasSize[0]*_devicePixelRatio, _canvasSize[1]*_devicePixelRatio);
|
|
_ctx.restore();
|
|
}
|
|
|
|
function hitTest(point){
|
|
_ctx.save();
|
|
_ctx.setTransform(1,0,0,1,0,0);
|
|
for(var i = 0 ; i < _curFloor.FuncAreas.length; i++) {
|
|
var funcArea = _curFloor.FuncAreas[i];
|
|
if((!funcArea.Category) && parseInt(funcArea.Type) == 100){ //hollow area
|
|
continue;
|
|
}
|
|
|
|
var rect = funcArea.rect;
|
|
if((point[0]<rect.tl[0] && point[0] < -rect.br[1]) || (point[0]>rect.br[0] && point[0] > -rect.tl[1]))
|
|
continue;
|
|
|
|
var poly = funcArea.newOutline;
|
|
if (poly.length < 6) { //less than 3 points, return
|
|
continue;
|
|
}
|
|
_ctx.beginPath();
|
|
|
|
_ctx.moveTo(poly[0], -poly[1]);
|
|
for (var j = 2; j < poly.length - 1; j += 2) {
|
|
_ctx.lineTo(poly[j], -poly[j + 1]);
|
|
}
|
|
_ctx.closePath();
|
|
|
|
if (_ctx.isPointInPath(point[0], point[1])) {
|
|
_ctx.restore();
|
|
return funcArea;
|
|
}
|
|
}
|
|
|
|
_ctx.restore();
|
|
return null;
|
|
}
|
|
|
|
this.loadSpirtes = function(mall){
|
|
if(mall != null && _sprites.length == 0 ){
|
|
var images = _map.theme().pubPointImg;
|
|
for( var key in images){
|
|
var loader = new THREE.ImageLoader();
|
|
|
|
var image = loader.load( images[key], function(image){
|
|
_this.render(mall);
|
|
})
|
|
|
|
_sprites[key] = image;
|
|
}
|
|
}
|
|
_sprites.isLoaded = true;
|
|
}
|
|
|
|
this.createNameTexts = function(floorId, mall){
|
|
if(_nameTexts.length != 0){
|
|
_nameTexts.length = 0;
|
|
}
|
|
var funcAreaJson = mall.getFloorJson(mall.getCurFloorId()).FuncAreas;
|
|
var fontStyle = _map.theme().fontStyle;
|
|
_ctx.font = fontStyle.fontsize + "px/1.4 " + fontStyle.fontface;
|
|
for(var i = 0 ; i < funcAreaJson.length; i++){
|
|
var name = {};
|
|
var funcArea = funcAreaJson[i];
|
|
if((!funcArea.Category) && ((parseInt(funcArea.Type) == 100) || (parseInt(funcArea.Type) == 300))){
|
|
name.text = "";
|
|
name.halfWidth = 0;
|
|
name.halfHeight = 0;
|
|
name.visible = false;
|
|
}else {
|
|
name.text = funcAreaJson[i].Name;
|
|
name.halfWidth = _ctx.measureText(name.text).width / 2;
|
|
name.halfHeight = fontStyle.fontsize / 4;
|
|
name.visible = true;
|
|
}
|
|
|
|
_nameTexts.push(name);
|
|
}
|
|
}
|
|
|
|
_init();
|
|
}
|
|
|
|
//---------------------Controller2D class-----------------
|
|
|
|
Controller2D = function(renderer){
|
|
var _renderer = renderer;
|
|
var domElement = _renderer.domElement;
|
|
this.domElement = ( domElement !== undefined ) ? domElement : document;
|
|
this.viewChanged = true;
|
|
this.enable = true;
|
|
|
|
var _startPos = [];
|
|
var _curPos = [];
|
|
|
|
var _this = this;
|
|
|
|
this.startPoint = [0, 0];
|
|
this.endPoint = [0, 0];
|
|
var _panVector = [0, 0];
|
|
var _zoomDistStart = 0, _zoomDistEnd = 0;
|
|
var _zoomScale = 1;
|
|
var STATE = {NONE: -1, ZOOM: 1, PAN: 2}
|
|
var _state = STATE.NONE;
|
|
|
|
this.reset = function(){
|
|
_this.startPoint = [0,0];
|
|
_this.endPoint = [0,0];
|
|
}
|
|
|
|
this.translate = function(){
|
|
_curPos[0] = (_startPos[0] + _panVector[0]);
|
|
_curPos[1] = (_startPos[1] + _panVector[1]);
|
|
IDM.DomUtil.setPos(domElement, [_curPos[0], _curPos[1]]);
|
|
}
|
|
|
|
this.zoom = function(){
|
|
var pos = IDM.DomUtil.getPos(domElement);
|
|
domElement.style[IDM.DomUtil.TRANSFORM] = IDM.DomUtil.getTranslateString(pos) + " scale(" + _zoomScale + ") ";
|
|
}
|
|
|
|
function touchStart(event){
|
|
|
|
event.preventDefault();
|
|
|
|
var touches = event.touches;
|
|
if(touches.length == 1){ //pan
|
|
_this.startPoint[0] = touches[0].clientX;
|
|
_this.startPoint[1] = touches[0].clientY;
|
|
var point = IDM.DomUtil.getPos(domElement);
|
|
_startPos[0] = point[0];
|
|
_startPos[1] = point[1];
|
|
|
|
}
|
|
else if( touches.length == 2){ //zoom
|
|
var dx = touches[1].clientX - touches[0].clientX;
|
|
var dy = touches[1].clientY - touches[0].clientY;
|
|
_zoomDistEnd = _zoomDistStart = Math.sqrt( dx * dx + dy * dy );
|
|
|
|
|
|
}
|
|
else{
|
|
_state = STATE.NONE;
|
|
return;
|
|
}
|
|
if(_this.enable === false) return;
|
|
|
|
document.addEventListener('touchend', touchEnd, false);
|
|
document.addEventListener('touchmove', touchMove, false);
|
|
|
|
|
|
}
|
|
|
|
function mouseDown(event){
|
|
|
|
event.preventDefault();
|
|
_this.startPoint[0] = event.clientX;
|
|
_this.startPoint[1] = event.clientY;
|
|
|
|
if(_this.enable === false) return;
|
|
|
|
document.addEventListener('mouseup', mouseUp, false);
|
|
document.addEventListener('mousemove', mouseMove, false);
|
|
|
|
var point = IDM.DomUtil.getPos(domElement);
|
|
_startPos[0] = point[0];
|
|
_startPos[1] = point[1];
|
|
|
|
|
|
|
|
}
|
|
|
|
function touchMove(event){
|
|
if(_this.enable === false) return;
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
var touches = event.touches;
|
|
if(touches.length == 1) {
|
|
_this.endPoint[0] = touches[0].clientX;
|
|
_this.endPoint[1] = touches[0].clientY;
|
|
|
|
_panVector = [_this.endPoint[0]-_this.startPoint[0], _this.endPoint[1]-_this.startPoint[1]];
|
|
_this.translate();
|
|
_state = STATE.PAN;
|
|
|
|
}else if( touches.length == 2){
|
|
var dx = touches[1].clientX - touches[0].clientX;
|
|
var dy = touches[1].clientY - touches[0].clientY;
|
|
_zoomDistEnd = Math.sqrt( dx * dx + dy * dy );
|
|
_zoomScale = _zoomDistEnd / _zoomDistStart;
|
|
_this.zoom( );
|
|
_state = STATE.ZOOM;
|
|
}
|
|
}
|
|
|
|
function mouseMove(event){
|
|
if(_this.enable === false) return;
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
_this.endPoint[0] = event.clientX;
|
|
_this.endPoint[1] = event.clientY;
|
|
|
|
_panVector = [_this.endPoint[0] - _this.startPoint[0], _this.endPoint[1] - _this.startPoint[1]];
|
|
|
|
if(event.button === 0) {
|
|
|
|
|
|
_this.translate();
|
|
_state = STATE.PAN;
|
|
}
|
|
else if(event.button === 1){
|
|
|
|
_zoomScale = (Math.abs(_panVector[0])+Math.abs(_panVector[1]))/1000;
|
|
if(_panVector[1] < 0){
|
|
_zoomScale = -_zoomScale;
|
|
}
|
|
_zoomScale += 1;
|
|
_this.zoom( );
|
|
_state = STATE.ZOOM;
|
|
}
|
|
|
|
}
|
|
|
|
function mouseWheel(event){
|
|
if(_this.enable === false) return;
|
|
var delta = 0;
|
|
delta = event.wheelDelta ? (event.wheelDelta / 120) : (- event.detail / 3);
|
|
delta > 0 ? delta *= 1.25 : delta *= -0.8;
|
|
_renderer.scale(delta);
|
|
}
|
|
|
|
function touchEnd(event){
|
|
if(_this.enable === false) return;
|
|
if(_state == STATE.PAN) {
|
|
panEnd();
|
|
}else if(_state == STATE.ZOOM) {
|
|
zoomEnd();
|
|
}
|
|
_state = STATE.NONE;
|
|
document.removeEventListener('touchend', touchEnd, false);
|
|
document.removeEventListener('touchmove', touchMove, false);
|
|
}
|
|
|
|
function mouseUp(event){
|
|
if(_this.enable === false) return;
|
|
if(_state == STATE.PAN) {
|
|
panEnd();
|
|
}else if(_state == STATE.ZOOM) {
|
|
zoomEnd();
|
|
}
|
|
_state = STATE.NONE;
|
|
document.removeEventListener('mouseup', mouseUp, false);
|
|
document.removeEventListener('mousemove', mouseMove, false);
|
|
}
|
|
|
|
function panEnd(){
|
|
if(Math.abs(_panVector[0]+_panVector[1]) < 5) return;
|
|
|
|
_renderer.updateViewport();
|
|
_renderer.translate(_panVector);
|
|
}
|
|
|
|
function zoomEnd(){
|
|
_renderer.updateViewport(true);
|
|
_renderer.scale(_zoomScale);
|
|
}
|
|
|
|
this.domElement.addEventListener('touchstart', touchStart, false);
|
|
this.domElement.addEventListener('mousedown', mouseDown, false);
|
|
this.domElement.addEventListener('mousewheel', mouseWheel,false);
|
|
|
|
|
|
} |