安卓端360度全景图的html5实现
这里是一款旅游相关的安卓应用,其中虚拟旅游的功能采用html5的360度全景图技术实现,使用户能够身临其境的感受旅游景点的风光。
此处引入了ddpanorama插件,它的原理是在canvas上绘制全景图,手指滑动时重绘canvas来实现。它包括通过手指滑动循环查看全景图,点击热点可进入另一全景图,缩放,离线访问等功能。
热点的计算和绘制:
可以在ddpanorama.js中看到在redraw这个方法也就是canvas重绘的时候定义了一个事件:
$(this.img).trigger(
jQuery.Event(ddpanoramas.event_prefix+"redraw", {
scrollX : scrollX,
canvas : this.canvas,
speed : $(this.canvas).prop("speedX") / ddpanoramas.max_speed,
loaded : loaded
}));
并且传出了一些参数,其中scrollX这个参数是针对原图比例的手指滑动时图片的偏移量,它在计算热点位置时起到至关重要的作用。因此在绑定ddredraw这个事件,在该事件触发时候进行热点的计算和绘制及点击事件的绑定。这里为了方便,我们还需要一个参数,就是针对canvas比例的手指滑动时图片的偏移量。这个在ddpanorama.js中setScrollX这个方法中的scrollX取得,我们可以定义一个全局变量canvasScrollX,将这个值存储起来,随时使用。
至于计算过程,需要慢慢调试,这里上个代码:
imgEle.ddpanorama({ width: bodyWidth, height: bodyHeight }).bind("ddredraw", function (event) {
var canvas = event.canvas;
var ctx = canvas.getContext("2d");
var imgNatualWidth = imgEle.get()[0].naturalWidth;
var imgNatualHeight = imgEle.get()[0].naturalHeight;
var fontSize = imgNatualHeight / 40;
if (hotPointInfo != null) {
for (var i = 0; i < hotPointInfo.length; i++) {
if (hotPointInfo[i] != null && hotPointInfo[i].PanImgHotType != null && hotPointInfo[i].PanImgInfoID != null && hotPointInfo[i].PanImgHotType == 0 && hotPointInfo[i].PanImgInfoID == GetHotPanImgInfoID) {
var hotPanImgInfoId = hotPointInfo[i].HotPanImgInfoID;
var scrollX = event.scrollX + hotPointInfo[i].HotPosX;
var canvasNatualWidth = bodyWidth * imgNatualHeight / bodyHeight; //原始图可见区域的宽
if (event.scrollX > 0) {
if (hotPointInfo[i].HotPosX > canvasNatualWidth) {
scrollX = event.scrollX - imgNatualWidth + hotPointInfo[i].HotPosX;
}
}
if (event.scrollX < -hotPointInfo[i].HotPosX - hotPointInfo[i].PanImgHotName.length * fontSize) {
scrollX = event.scrollX + hotPointInfo[i].HotPosX + imgNatualWidth;
}
ctx.beginPath();
ctx.globalAlpha = 0.6;
ctx.fillStyle = "black";
showRoundRect(ctx, scrollX - fontSize, hotPointInfo[i].HotPosY - fontSize * 4 / 3, (hotPointInfo[i].PanImgHotName.length + 2) * fontSize, fontSize * 2, fontSize / 2);
ctx.globalAlpha = 1;
showText(ctx, fontSize + "px 微软雅黑, Arial", "#fff", hotPointInfo[i].PanImgHotName, scrollX, hotPointInfo[i].HotPosY);
ctx.closePath();
}
}
}
$(canvas).unbind("click").click(function (e) {
var mouseCoord = getMouseCoord(e);
var isOnHotPoint = false;
if (hotPointInfo != null) {
for (var i = 0; i < hotPointInfo.length; i++) {
if (hotPointInfo[i].PanImgHotType == 0) {
var canvasX = hotPointInfo[i].HotPosX * bodyHeight / imgNatualHeight;
var canvasY = hotPointInfo[i].HotPosY * bodyHeight / imgNatualHeight;
var totalWidth = imgNatualWidth * bodyHeight / imgNatualHeight;
var canvasFontSize = fontSize * bodyHeight / imgNatualHeight;
if (canvasScrollX < bodyWidth - canvasX && canvasScrollX > -canvasX - hotPointInfo[i].PanImgHotName.length * canvasFontSize - 20) {
var isOntheArea = detectMousePos(mouseCoord, canvasScrollX + canvasX - canvasFontSize * 2, canvasY - canvasFontSize * 2, (hotPointInfo[i].PanImgHotName.length + 4) * canvasFontSize, canvasFontSize * 4);
if (isOntheArea == true) {
isOnHotPoint = true;
}
canvasClick(isOntheArea, hotPointInfo[i].HotPanImgInfoID);
} else if (canvasScrollX > -canvasX || canvasScrollX < bodyWidth - canvasX - totalWidth) {
var isOntheArea;
if (canvasX + canvasScrollX - totalWidth - canvasFontSize * 2 < 0) {
isOntheArea = detectMousePos(mouseCoord, canvasX + canvasScrollX + totalWidth - canvasFontSize * 2, canvasY - canvasFontSize * 2, (hotPointInfo[i].PanImgHotName.length + 4) * canvasFontSize, canvasFontSize * 4);
} else {
isOntheArea = detectMousePos(mouseCoord, canvasX + canvasScrollX - totalWidth - canvasFontSize * 2, canvasY - canvasFontSize * 2, (hotPointInfo[i].PanImgHotName.length + 4) * canvasFontSize, canvasFontSize * 4);
}
if (isOntheArea == true) {
isOnHotPoint = true;
}
canvasClick(isOntheArea, hotPointInfo[i].HotPanImgInfoID);
}
}
}
}
//去除隐藏缩略图
if (!isOnHotPoint) {
// showOrHide();
}
});
try {
isOnLine = Virtual.checkConnectNet();
} catch (e) {
hideloding();
}
if (isOnLine == 1) {
localStorage.setItem("virtualTravelInfoObj" + sceAreaId, JSON.stringify(virtualTravelInfoObj));
}
hideloding();
});
这里如何获取点击事件呢?
将整个canvas元素绑定click事件,然后通过click事件触发的坐标来计算,需要引入以下两个方法:
//获取鼠标事件的坐标
function getMouseCoord(e) {
var mx = 0,
my = 0;
if (e.layerX || e.layerX == 0) {
mx = e.layerX;
my = e.layerY;
} else if (e.offsetX || e.offsetX == 0) {
mx = e.offsetX;
my = e.offsetY;
}
var coord = { x: mx, y: my };
return coord;
}
//检测鼠标是否在某个区域里
function detectMousePos(mouseCoord, x, y, w, h) {
var isOntheArea = false;
if (mouseCoord.x > x && mouseCoord.x < x + w && mouseCoord.y > y && mouseCoord.y < y + h) {
isOntheArea = true;
}
return isOntheArea;
}
宽高自适应屏幕:
在插件初始化时候传入width,height可以设置canvas的宽高:
imgEle.ddpanorama({ width: bodyWidth, height: bodyHeight });
js获取屏幕宽:screen.availWidth,屏幕高:screen.availHeight
由于在移动端屏幕顶部有信号条,还有app壳占用了一些高度,所以更好的办法是由客户端开发人员通过url参数传webview的宽和高的值给我们调用。
离线访问:通过离线缓存和本地存储结合使用来实现。
设置一个全局对象来缓存数据(一般是JSON格式),每次ajax请求的数据都缓存在该对象中,待所有数据取得后,将该对象通过JSON.stringify方法转换成字符串格式,然后存到localStorage中。
通过navigator.onLine来判断网络状态(目前测过chrome支持),但在手机中会出现无效的情况,这时候客户端提供一个接口来判断网络状态,如果是onLine,那么ajax请求数据,如果是offLine,那么从localStoage中取数据,然后通过JSON.parse方法转换为JSON格式的对象。
对于嵌在APP中的网页来说,离线缓存和本地存储都需要客户端代码的支持,不然目前会出现无效的情况,这点要注意。
安卓端360度全景图的html5实现的更多相关文章
- HTML5 Canvas实现360度全景图
原文:http://blog.csdn.net/jia20003/article/details/17172571 很多购物网站现在都支持360实物全景图像,可以360度任意选择查看样品,这样 对购买 ...
- Three.js制作360度全景图
这是个基于three.js的插件,预览地址:戳这里 使用方法: 1.这个插件的用法很简单,引入如下2个js <script src="js/three.min.js"> ...
- JS+CSS3 360度全景图插件 - Watch3D.js
日常闲扯 从上一篇文章到这篇中间快过了一年了,时间真滴过得快.不是在下中间没想过写新的文章,而是自己确实变懒了(体重+1 +1 +1 +1....) ..OTL...不过到最后觉得还是需要写点东西,不 ...
- html5人物图片360度立体旋转
体验效果:http://hovertree.com/texiao/html5/10.htm 下载:http://hovertree.com/hvtart/bjae/t16oddyt.htm 代码如下: ...
- 利用Canvas实现360度浏览
前言:最近几个月来到新公司,主要从事移动端方面的开发,有时候也挺忙挺累的,于是就好一段时间没写博客了.其实自己在这几个月里,自己对canvas以及createjs和egret都有了一定程度上的认识与掌 ...
- 基于Three.js的360X180度全景图预览插件
基于Three.js的360X180度全景图预览插件 时间 2015-08-12 10:01:10 HTML5中国 原文 http://www.html5cn.org/article-8621-1 ...
- 融云技术分享:融云安卓端IM产品的网络链路保活技术实践
本文来自融云技术团队原创分享,原文发布于“ 融云全球互联网通信云”公众号,原题<IM 即时通讯之链路保活>,即时通讯网收录时有部分改动. 1.引言 众所周知,IM 即时通讯是一项对即时性要 ...
- jQuery Panorama Viewer – 360度全景展示插件
jQuery Panorama Viewer 这款插件可以帮助你在网站中嵌入全景图片.要做到这一点,首先只需要在页面中引入最新的 jQuery 库,以及 jquery.panorama_viewer. ...
- 使用Javascript来创建一个响应式的超酷360度全景图片查看幻灯效果
360度的全景图片效果常常可以用到给客户做产品展示,今天这里我们推荐一个非常不错的来自Robert Pataki的360全景幻灯实现教程,这里教程中将使用javascript来打造一个超酷的全景幻灯实 ...
随机推荐
- WPF去边框与webbrowser的冲突
首先建一个类,比如NativeMethods.cs class NativeMethods{ public const int WS_CAPTION=0x00C0000; public ...
- "传成老树白茶"献礼母亲节 邀市民品茗感受茶文化
5月8日下午,传成老树白茶巡回中国公益品鉴会第七十站,走进福州马尾区东方名城传成老树白茶文化馆. 本次品鉴会活动以“感恩母亲节”为主题,以马尾船政文化为背景,邀福州市民一起品鉴白茶,感受中国茶文化. ...
- MongoDB 效率
写入: 插入100万条数据:用InsertMany,耗时16s左右. 读取: 读取300万条数据,耗时3600毫秒.
- jQuery简单实现iframe的高度根据页面内容自适应的方法(转)
本文实例讲述了jQuery简单实现iframe的高度根据页面内容自适应的方法.分享给大家供大家参考,具体如下: 方式1: //注意:下面的代码是放在和iframe同一个页面中调用 $("#i ...
- user agent stylesheet (浏览器默认样式)!
"-webkit-margin-before". "-webkit-margin-after". "-webkit-margin-start" ...
- Android Studio中Button等控件的Text中字符串默认大写的解决方法
初学Android的时候,在Android Studio中xml里面添加一个Button.EditText等控件后,它的Text总是会显示大写,即使你输入的字符串是小写也不行,控制字符串大小写的属性是 ...
- 基于DevExpress实现对PDF、Word、Excel文档的预览及操作处理
http://www.cnblogs.com/wuhuacong/p/4175266.html 在一般的管理系统模块里面,越来越多的设计到一些常用文档的上传保存操作,其中如PDF.Word.Excel ...
- 题目:求1+2+…+n,
题目:求1+2+-+n, 要求不能使用乘除法.for.while.if.else.switch.case等关键字 以及条件判断语句(A?B:C). java 实现 public class sum { ...
- TOP 和 OFFSET 筛选(转)
SQL Server 对行数的排序提供了 TOP 筛选.SQL Server 2012 新增了 OFFSET 筛选. 一.TOP 筛选 如果有 ORDER BY 子句,TOP 筛选将根据排序的结果返回 ...
- shell命令大全
请跳转至:http://www.lampweb.org/linux/2/3.html