Stonelee's Blog

如无必要,勿增实体

chrome15中无法使用svg的currentScale方法

分享到: 更多

测试网址

已提交bug,待解决

ps

chrome开发者已添加Labels: -Area-Undefined Area-WebKit

ps

chrome 13中是可以缩放的,因此继续研究,结果在定点缩放这一功能实现时发现大问题:

放大,即currentScale *= 1.1时, 当前鼠标的clientX减小,即event.clientX /= 1.1, 但是图形中的点clientX不变

移动,即currentTranslate.x -=10 时, 当前鼠标clientX不变, 但是图形中的点clientX -=10

即缩放是浏览器行为,不改变图形client坐标,而移动是svg行为,会改变图形client坐标。

两者的实现如此不一致,怪不得chrome 15中currentScale失效了,而currentTranslate没有。 Google是不是把资源都放到canvas上了,svg这么明显的bug都不管。。。

firefox下都是图形坐标改变,鼠标不变。很容易就能实现定点缩放功能。

ps

经反复研究发现,ie端支持svg的Chrome Frame方案不够成熟,该控件体积有20多M,安装需要几分钟,而且时常安装失败,安装体验太差。最重要的是chrome中svg缩放移动条件下鼠标定位与svg坐标换算非常诡异,经两天研究仍无法完美解决,导致无法实现定点缩放功能。页面初次加载也不够快(可能是gcf方式加载的问题),用户体验一般。 所以…放弃…

换用Adobe svg viewer吧。。。

IE6下渲染svg的解决方案

分享到: 更多

IE6下svg的渲染是个问题,目前主要有以下几种解决方案:

svgweb

优点:开源,可在不支持svg的浏览器中使用flash来渲染,有效解决客户端下载插件问题

缺点:svg封装不完全,flash渲染效率比较低,刷新页面时内存泄漏严重

adobe SVGViewer

优点:对svg支持较好

缺点:adobe已于2009年1月份明确表示不再提供支持,需要客户端下载插件

Chrome Frame

优点:IE下使用chrome模式来渲染,速度快,原生支持svg

svgweb+chrome frame

这时目前我们项目组所使用的解决方案,可以较好地满足我们的需求

  • 系统整体框架为遗留系统,IE only,这决定了我们的客户必须使用IE(煤矿客户本来就对此喜闻乐见)
  • 一般客户端使用频率较低,使用svgweb提供的flash渲染,不用下载flash以外的插件
  • 监控中心中客户端数量较少,而且设备可控,使用chromeframe渲染svg单页面,渲染效率高,减少内存泄漏

发现问题:

在实际使用过程中发现,使用frame方式调用svg单页面时,通过指定chromeframe渲染头的方式是无效的:

1
<meta http-equiv="X-UA-Compatible" content="chrome=1">

此时访问调用frameset的页面,会发现其依然是IE渲染,而单独访问该svg页面会使用chrome方式。

网上讨论结果是目前chromeframe只支持顶层meta tag检测,而且貌似也不打算修正这一问题。

解决方案:

经过不断尝试,发现有一个取巧方法可以解决此问题,即使用gcf前缀指定渲染方式,形如gcf:http://gmail.com 猛击 参考网址

这需要修改注册表:HEKY_CURRENT_USER\Software\Google\ChromeFrame下新建DWORD类型的键 AllowUnsafeURLs=1 然后就可以这样调用该svg页面

1
<frame src="gcf:http://127.0.0.1/svg/index.html" name="MainFrame" id="MainFrame"  frameborder="0" />

如果要兼容没有安装chromeframe的浏览器,可以使用js动态更改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(function() {
  function IsGCFInstalled() {
      try {
          if (new ActiveXObject('ChromeTab.ChromeFrame')) {
              return true;
          }
      } catch(e) {}
      return false;
  }

  $(document).ready(function() {
      var frame = document.createElement('frame');
      frame.setAttribute('name', 'MainFrame');
      frame.setAttribute('id', 'MainFrame');
      frame.setAttribute('frameborder', '0');
      if (IsGCFInstalled()) {
          frame.setAttribute('src', 'gcf:http://10.10.22.84/develop/gmf/zhunqi/index.html');
      } else {
          frame.setAttribute('src', 'zhunqi/index.html');
      }
      $(frame).appendTo($('#TreeFrameSet'));
  });
})();

ps

注册表中指定RenderInGcfUrls的方法也是无效的,原因估计等同于指定meta tag的方法。

打造纯净前端开发环境(附nginx反向代理解决跨域问题)

分享到: 更多

最近在搞前端javascript编码, 公司项目使用的后台语言是.net和java,这些东西对于我而言太笨重了。而我钟爱的python又由于种种原因不能应用到项目中。因此需要一个比较纯净的前端开发测试环境,开发出来的代码可以容易的供其他后端语言使用。

要求

  • 能够实现前后台数据通信
  • 保持前端纯洁性,不掺杂过多服务端代码
  • 前端js使用相对url来获取数据,需要解决跨域问题

解决方案

静态服务器nginx

提供前端html+js+css的静态展示

需要配置nginx.conf: alias可以指定映射路径, autoindex可以自动列出文件目录

1
2
3
4
location /develop {
  alias       "/home/lxd/Develop";
  autoindex   on;
}

后台测试服务器tornado

不使用template_path和static_path,直接使用write来返回字符串数据, 服务端简化到只需一个文件, tornado只用来产生数据,以独立应用的形式提供服务

跨域问题

使用nginx反向代理tornado服务器,来解决跨域问题

nginx.conf添加反向代理

1
2
3
4
5
6
location /develop/gmf/zhunqi/tornado {
  proxy_pass       "http://localhost:8888";
  proxy_redirect   off;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

tornado文件指定url映射

1
(r"/develop/gmf/zhunqi/tornado/mines", MineHandler),

解决ubuntu中激活显卡驱动导致启动黑屏问题

分享到: 更多

今天重新安装了ubuntu,准备作为个人开发的主环境。

晚上的时候忽然蹦出来个激活硬件驱动的提示,我手贱了下随手就点了,结果重启后系统就进不去了,一直是黑屏,连ctrl+alt+F1都进不去。

解决方法

重启,在GRUB中按e进入编辑,删除quiet and splash,如果是Nvidia显卡添加nomodeset,如果是ATI显卡添加nomodeset xforcevesa

按ctrl+x启动,然后会提示说找不到桌面,这时可以进入命令行了,删掉xorg.conf

1
2
cd /etc/X11/
sudo rm xorg.conf

然后就可以正常startx了

基于WebGL的魔兽争霸Demo

分享到: 更多

早就想基于魔兽争霸的模型做点东西,周末抽空研究了下,比较简单。

先看看效果。

导出魔兽争霸模型

Warcraft 3 Viewer可以读取warcraft的MPQ文件,从中选择中意的模型,然后可以分别将MDX和texture导出。为了后面使用的方便,texture导出到和mdx相同目录下,格式为jpg。

导入到blender

使用modelconv来将mdx文件转换为obj文件。modelconv是一个命令行程序,调用后,输入要转换的mdx文件名和要转换成的obj文件名即可。 然后使用blender来import该obj文件。

调整模型

自动导入的文件往往其大小和角度不符合实际需要,因此需要进行调整。

  • 缩放模型
  • 调整模型位置
  • 调整摄像机位置
  • 删掉多余的面

贴纹理(texture)

打开UV/Image Editor,打开贴图文件,在3D View视图中查看Textured视角,这时会发现模型已经自动贴好了纹理。但是这时候render的话会发现渲染出的模型依然是难看的灰色。因此需要新加一个Material,然后新加一个Texture,Type选择Image or Movie,Image选择之前的贴图文件,Mapping中Coordinates选择UV,这样才算真正贴好了纹理。

导出three.js模型

使用ThreeJS自带的blender导出插件,会自动将模型和纹理导成ThreeJS需要的json。只需将生成的js文件和texture复制到ThreeJS项目中即可正常使用。

ThreeJS中调用模型

注意调整模型位置,纹理会自动贴好。

1
2
3
4
5
6
7
8
9
10
var loader = new THREE.JSONLoader();
loader.load( { model: "warcraft/archer.js", callback: createScene } );

function createScene( geometry ) {
    var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial());
    mesh.position.x=-15;
    mesh.position.y=-5;
    mesh.scale.x = mesh.scale.y = mesh.scale.z = 4;
    scene.addObject( mesh );
}

基于WebGL的矿井三维演示

分享到: 更多

用了一周的时间研究WebGL相关技术,发现该技术竟然已经发展到如此地步,足以应用于企业开发领域。因此我使用Blender建模,基于ThreeJS实现了一个能够在浏览器上运行的矿井结构的三维效果展示。

浏览器兼容

Chrome和Firefox的较新版本均可流畅运行, IE8需要借助ChromeFrame插件

平台兼容

基于浏览器的应用,完美跨平台。 经测试在手机Android2.3的Firefox中也可以显示。

主要功能

  • 鼠标对模型的自由旋转、缩放、平移
  • 巷道文字显示
  • 人员移动轨迹回放,在模型中显示
  • 传感器在巷道模型上定点显示
  • 点击传感器,显示从后台服务器中取得的环境参数
  • 轮询方式从后台取得报警信息,在界面上展示。
  • 使用DAT.GUI实现模型参数的实时显示和动态更改。

感想

发展眼光很重要。新技术浪潮的到来往往会伴随行业洗牌,传统巨头会在一系列历史遗留问题中纠缠不清,无法很好的转移航向来适应未来的发展。新入行者恰恰可以利用后发优势,凭借新技术的潮头,爆发似的抢占市场。新技术不可怕,可怕的是技术上畏首畏尾,不敢突破的心态。跟在别人屁股后面永远只能吃那个。勇于打破既有规则,实现对既有规则的颠覆,建立自己的游戏规则,自己带着别人在圈子里玩,这才是我们应该做的事情。

跨平台很重要,未来不再是windows的天下,随着智能手机和平板电脑的日益普及和流行,Linux系愈发强势。微软早就不是以前的巨无霸,谷歌苹果已经成为新生代的巨头。.net系的技术经常随市场一变再变,千万不要妄想抱住某厂商的大粗腿,民主化的开源社区才是王道(当然没有各大厂商的财力支持也是白搭)。

基于浏览器的应用开发很重要,基于云端的浏览器应用是业界趋势。虽然基于系统原生的程序性能更强,用户体验更好,但是多平台开发需要多语言的移植,对于小公司来说从无论从人力物力还是发维护成本都是不可能的。而且根据摩尔定律,硬件性能越来越强,价格越来越便宜,我们要做的只是等待,而且不会等待太久。

人很重要。好的程序员的工作效率会是垃圾程序员的数十倍,但是工资往往不需要这么多,他们更希望的是得到认可、得到尊重。好的程序员是自我管理的,他们无聊的时候也在学习,因为这是一种乐趣,他们工作效率极高,但从不加班。他们厌恶浪费生命的会议,厌恶一切不必要的手续和流程,厌恶一切没理由的说教和唠叨,推崇使用最简单最有效的方法来解决最复杂的问题。天外飞仙,一剑封喉。

搭建基于github的免费博客

分享到: 更多

优势

  • 国外著名开源网站,影响力大(无声无息倒掉的风险较少)
  • 基于git的本地源码控制,安全(防GFW)
  • 纯文本写作,适合程序控
  • 可以绑定自己的域名
  • 空间免费

使用

  • fork我的博客
  • git clone
  • 修改一下页面代码,在_posts中写自己的博客
  • github page服务后台使用jekyll,为了在本地写作博客, 修改满意后再进行同步,自己安装jekyll是很有必要的。 然后可以在本地启动
1
jekyll --server

功能增强

绑定域名

修改 A record并指向207.97.227.245

我在Godaddy买的域名,还没用就被封DNS了。更换Nameservers后成功访问。使用的是 dnspod,据说是国内最早提供免费智能DNS产品的网站,需要邮箱和手机验证。

参考

模板引擎liquid,是模版使用的语法

textile

语法高亮支持语言

pygments

模版网址

基于html5、css3的免费模板

PS

2012-05-05更新

jekyll安装:

1
$ gem install jekyll 0.11.0

遇到问题:

1
Liquid error: undefined method `join’ for #

解决方法: liquid降级

1
2
$ gem uninstall liquid
$ gem install liquid -v 2.2.2

糅合Markdown和语法高亮,快速写作技术博客

分享到: 更多

之前博客在javaeye,不知道触犯了老大哪根神经,不声不响就给封了,现在来到CSDN,又正好赶上改版,好好的博客写完后格式乱七八糟。国内的其他博客商也都好不到哪里去,不知道什么时候就被封,算了,自己动手丰衣足食,自己搞个独立博客吧。

要求

代码写惯了,觉得可视化编辑器非常不靠谱,写代码花时间,写文档花时间,调格式更得花时间,而且不利于备份。因此要求纯文本,标记语言简单易学,实现代码高亮。

技术选型

  • 标记语言 Markdown
  • python封装库 python-markdown2
  • 代码高亮工具 Javascript code prettifier

实现

1. markdown实现:

1
2
3
import markdown2
content="something"
markdown = markdown2.markdown(content)

字符串content会按照markdown的语法生成相应的html标签,直接输出到页面上即可。

2. Javascript code prettifier使用:

引入js文件和选择的css模板

1
2
<script src="prettify.js"></script>
<link rel="stylesheet" href="desert.css" type="text/css" />

函数加载到页面中:

1
2
<script src="prettify.js"></script>
<body onload="prettyPrint(); ">

代码插入:

1
2
3
4
5
<div style="width: 40em; display: inline-block">
    <pre class="prettyprint">
        somecode
    </pre>
</div>

python-markdown2中已经实现了代码高亮,无奈语焉不详,而且语法也着实丑陋。本着“quick and dirty”的原则,直接定义

1

来包裹想高亮的代码,然后用replace来替换上面的div,pre标签。

实现如此简单~

样例

源文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
标题
====

前言

**目录**

* 第一章
 * 第一节
 * 第二节
* 第二章
* 第三章

第一章
------

**第一节**

内容内容内容内容内容内容

**第二节**

<code>
def hello()
    print "hello"
</code>

第二章
------

内容内容内容内容内容内容

附有用的网址

Markdown

代码高亮 Javascript code prettifier

LINQ流水线

分享到: 更多

linq帅呆了~这一刻函数编程附身

1
2
3
4
5
6
7
8
9
10
11
12
//处理废票文本框中用户的输入
private List<int> getDirtyNumList(int startNum, int endNum, string txtDirtyNums)
{
    return txtDirtyNums.Trim(new char[] { ' ', ',', ',' })//去掉头尾的空格或者逗号
                        .Split(new char[] { ',', ',' })//将字符串分割为数组
                        .Where(key => Regex.IsMatch(key, @"^\d+{1}quot;))//数字
                        .Select(key => Convert.ToInt32(key))//转格式
                        .Where(key => key >= startNum && key <= endNum)//必须在范围内
                        .OrderBy(key => key)//排序
                        .Distinct()//去重复
                        .ToList();
}

Tornado模板机制分析

分享到: 更多

Tornado自带的模板系统非常有特色,相对django等框架来说,可以任意插入python语句,这对于前后台通吃的小团队和个人开发者来说非常方便,而且可以方便的从Tornado框架中剥离出来单独使用。下面简单研究一下模板的实现机制。

模板的实现集中在template.py中,之所以可以随意在模板文本中插入python语句,是因为代码运行时会直接将文本转成python代码。这是如何实现的呢?

1
exec self.compiled in namespace

exec是python的内置语句,其作用是动态执行python代码,第一个参数可以是string,可以是打开的file object,也可以是code object。可以使用in来引入环境变量。这句代码的意思就是在namespace所设定的环境变量中,执行self.compiled的代码。

那么self.compiled从何而来呢?

1
self.compiled = compile(self.code, self.name, "exec")

使用exec执行python字符串时,需要先用解释器将其编译为字节代码,为避免多次编译导致没必要的时间消耗,可以预先进行编译。

compile(source,filename,mode[,flags[,dont_inherit]])可以将字符串编译为字节代码,其中source是要被编译的字符串,filename是定义该字符串变量的文件,如果不需要的话推荐设置为,mode指定编译类型(single指单个语句,exec指多个语句,eval指一个表达式)。

exec实际上会动态生成函数_execute(),而且将环境变量插入namespace中,这样就可以从namespace中再取出该函数,然后执行,其结果就是以python代码的方式完成模板文本的解析。

1
2
3
execute = namespace["_execute"]
try:
     return execute()

那么self.code是怎么生成的呢?

1
2
3
reader = _TemplateReader(name, template_string)
self.file = _File(_parse(reader))
self.code = self._generate_python(loader, compress_whitespace)

详细代码可以参见template.py,纯粹是字符串的解析,有时间再看吧。