在 Tizen 上依据你的照片使用Raphael JS 库创建拼贴的方法

简介 & 先决条件

: 在阅读本文之前我们建议您先去熟悉"Working with Raphael JS Library on Tizen"文章,该文中我们已经介绍了Raphael JS 库和库所提供的一些常用功能。

这篇文章描述了拉斐尔 JS 库所提供的一些功能。 您将学习: 如何绘制文本和图像,如何对其进行操作 (翻译、 旋转、 缩放),如何处理它们的属性,如何将"发光"效果应用于图像,等等。 您将了解在Tizen文件系统中如何将创建的拼贴画保存为PNG文件。 本文提供的示例应用程序"CollageCreator",演示了这些功能和更多的用法。

启动后,你可以在屏幕的左侧看到一个空的"canvas",在屏幕的右侧看到一个工具栏。 此工具栏包含以下选项:"文本"、"形象"、"属性","向上"、"向下"、"Bask"、"清除"、"保存","关闭"。 第一和第二个允许创建文本对象和图像对象。 使用"属性"按钮,您可以修改所选元素的属性。 "上"和"下"选项允许组织项目 (如更改它们的顺序)。 "Bask"按钮删除选定的对象,和"Clear"选项删除“canvas”中所有元素。 "Close"按钮关闭此应用程序。

图1 示例应用程序的屏幕截图

CollageCreator 示例应用程序需要:

它是一个小的 JavaScript 库,使您能够使用 Tizen Web 应用程序中的矢量图形。 它使用 SVG W3C 推荐标准和 VML。 库在SVG对象上运行,每个库也是 SVG DOM 对象,它们允许将事件处理程序附加到自己身上。

我们可以在“Working with Raphael JS Library on Tizen”文档中的“Getting started with Raphael JS Library”章节了解如何使用Raphael JS库。 有关拉斐尔 JS 库的详细信息和一些令人惊叹的demo,请访问 raphaeljs.com。 可在此处到该文档。 有个很好的网页,显示了 Raphael JS 库的各种功能,请参见。

  • Canvg,

它是一个 SVG 解析器和渲染器,允许svg到canvas转换。 正如 canvg 所需的 rgbcolor.js 类,它是在 MIT 许可下发布。

  • Svgfix,

现在我们知道,使用 canvg,我们可以将 SVG 转换为canvas。 然而,拉斐尔JS生成的SVG是没有得到很好的格式化。 Svgfix 是一个 JavaScript 函数,采用 (由拉斐尔 JS 生成的) 一个 SVG 字符串作为参数,并进行一些修改。 结果作为参数传递给 canvg。

 

CollageCreator 示例应用程序是基于Tizen SDK 2.1.0开发的,包括了 jQuery Mobile 1.3.1 和 jQuery 1.9.1 库。

意: 为便于参考,这篇文章使用/描述的特定功能,已经超链接到拉斐尔文档中的适当部分。

使用Raphael JS您可以绘制: 形状、 文本和图像。 "Working with Raphael JS Library on Tizen"中的"Drawing Shapes & Paths"一节介绍了如何绘制形状。 这篇文章描述了绘制文本和图像。

绘制文本

若要使用拉斐尔 JS 框架,你需要一个可以在上面绘画的对象,即Raphael paper。 它是由 Raphael() 函创建的。 此函数可以使用几个不同的参数集。 示例应用程序使用以下参数:

paper = new Raphael(container, container.clientWidth, container.clientHeight)

下面的代码片段说明了什么是"container":

<!-- index.html file: -->
<div id="container"></div>

// collage.js:
container = document.getElementById('container');

当你有一个Raphael paper时,你可以把它作为参数传递给 TextObject() 函数,用来创建一个文本元素,对其进行初始化,并存储有关它的属性的信息 (请参阅./ js/textObject.js)。

this.element = this.paper.text(300, 300, textContent);

Paper.text() 数在Raphael paper上绘制一个字符串,使用参数如下: x 和 y 坐标的位置,要绘制的文本字符串。 最后它返回一个Raphael 元素。

:Raphael 的坐标系统与canvas的坐标系统相同。

您可以定义文本元素为这样的属性: 大小、 重要性、 字体的颜色和内容。

图 2 设置文本元素的属性

图 3 显示了新创建的文本元素:

 

图 3 选定的文本元素

            

图 4 未选定的文本元素

要移动文本,你可以使用它下面的rectangle元素,要旋转文本则使用它左边的circle元素。

绘制图像

要创建一个图像元素,你必须将所选的图像 (URI) 传递给 addImage() 函数。

单击"Image"工具栏中的选项将显示一个弹出式窗口,带有两个选项。 "Choose the file"选项将显示"Media"页,在其中您可以选择您想要的图像,并添加到您的拼贴上。 

图 5"Media"视图

所选的图像必须有适当的扩展名 (".jpg"或".png")。 如果你想要知道更多关于模块是如何负责管理"Media"视图的,请参阅./ js/mediaList.js。

选择一个图像后, 其 URI 被传递给 addImage() 函数:

addImage : function(uri) {
    var img = new Image();
    img.onload = function() {
        if (this.width > this.height) {
            var scaledWidth = 200 / this.height * this.width;
            var scaledHeight = 200;
        } else {
            var scaledWidth = 200;
            var scaledHeight = 200 / this.width * this.height;
        }

        var imgObj = new ImageObject(paper, uri, scaledWidth,
                scaledHeight);

        imgObj.element.pos = elements.length;
        elements[elements.length] = imgObj.element;
    };
    img.src = uri;
},

缩放图像的大小。 新创建图像的最大维度等于 200 (对于宽度和高度)。 接下来,调用 ImageObject() 函数。 它将创建一个图像元素,初始化该图像元素并存储有关它的属性信息 (请参阅./ js/imageObject.js)。

this.element = this.paper.image(src, 100, 100, width, height);

Paper.image() 数将一个图片嵌入到拉斐尔纸上。 它采用下列参数: 源图像的URI,x 和 y 轴坐标位置、 图像的宽度和图像的高度。 最后返回Raphael元素。

您可以更改图像元素的‘opacity’ 度属性,并将"glow"效果添加到此元素,稍后我们会描述该元素。

图 6 设置图像元素的属性

新创建的图像元素如下所示:

图 7 选择的图像元素

要移动图像,你只需拖动它就可以了。 要旋转它,你可以使用它左侧的绿色圆圈 — — 左上角的紫色圆圈。

将拼贴保存到文件

将拼贴保存到文件不会像它看起来的那么难。 Raphael JS 生成 SVG 元素。 你必须将其转换为画布,而该画布可以保存为 PNG 文件。 若要将SVG转换为画布,你可以使用 canvg 分析器,这篇文章的"介绍 & 先决条件"一节中有描述。 然而,由Raphael JS 生成 SVG 并不是最适合canvg的格式。 要解决此问题,我们使用 PHPepe所提出的解决方案 — — svgfix 分析器。

将拼贴保存到文件中:

使用 svgfix 解析器修复由Raphael JS 生成 SVG

我们在id为“container”元素中绘制Raphael纸(请参阅这篇文章的"绘图文本"部分)。 要获取由Raphael JS 生成的 SVG,使用此 DOM 元素的innerHTML属性:

var innerSVG = container.innerHTML;

你唯一需要做的是使用 svgfix() 函数修复生成的 SVG 字符串 (请参阅./js/lib/external/svgfix-0.2.js 文件)。 它将你想要修复的SVG 字符串作为参数 :

var fixedSVG = svgfix(innerSVG);

使用 canvg 分析器将你已修复的 SVG 字符串转换成画布

现在,您可以使用 canvg() 函数:

canvg("canvas-result", fixedSVG, {
    renderCallback : function() {
        render();
    }
});

Canvg() 函数可以接受零个、 两个或三个参数。 在这种情况下,它使用的所有三个参数: 画布元素的id,已修复的 SVG 字符串和可选的参数:"renderCallback"函数,该函数在画布渲染结束后调用。

: 更多关于canvg() 函数使用的参数详细信息,请参阅./js/lib/external/canvg.js 文件。

使用 toDataURL() 函数将绘图画布转换成 PNG URL

Render () 函数如下所示:

var render = function() {
    var can = document.getElementById('canvas-result');

    try {
        var dataURL = can.toDataURL("image/png").replace(
                'data:image/png;base64,', '').replace('data:,', '');
        if (dataURL === '') {
            tlib.logger.err("No image source");
        } else {
            if (filename === '') {
                $("#filename-popup").show();

                $("#filename-save").unbind().bind("click", function() {
                    filename = $("#filename-input").val() + ".png";
                    $(".popup").hide();
                    createFile(dataURL);
                });
            } else {
                createFile(dataURL);
            }
        }
    } catch (e) {
        tlib.logger.err('canvas.toDataUrl error: ' + e.message);
        alert("Data source error: " + e.message);
        return;
    }
};

ToDataURL() 函数负责将绘图画布转换成 PNG 。 它将返回包含图像描述信息(类似PNG)的URI。

将创建的 PNG URL 保存到新创建的文件,文件扩展名为".png"

若要将创建的 PNG URI保存到文件中,我们使用 createFile() 函数:

var createFile = function(content) {
    var newFile = new tlib.file({
        filename : filename,
        virtualRoot : "images",
        success : function() {
            newFile.write(content, {
                success : function() {
                },
                error : function() {
                    tlib.logger.err("Text not written to the file");
                }
            });
        },
        error : function() {
            tlib.logger.err("File not created");
        }
    });
};

它使用 tlib.file 模块所提供的功能来创建和写入该文件。 有关它的详细信息请参阅./js/lib/tlib/tlib.file.js 文件。

我们创建的示例拼贴使用了示列应用程序:

使用属性

“Working with Raphael JS Library on Tizen”文章的“Working with attributes” 一节中介绍了如何更改Raphael元素的属性。 这里,我们主要关注可应用于图像元素的"glow"效果。

图 8 应用了"发光"效果的图像元素

您可以设置此类属性为"发光"效果: 

图 9 图像属性弹出菜单

要应用发光效果,您需要调用 Element.glow ([properties]) 函数。 您可以使用glow的某些属性(所有都是可选的):

  • width {Number} glow的大小,默认为10
  • opacity {Number} glow的不透明度,默认为0.5
  • offset-x {Number} 水平偏移,默认为0
  • offset-y {Number} 垂直偏移,默认为0
  • fill {Boolean} 是否需要填补glow,默认为false
  • color {String} glow的颜色,默认为黑色

转换

“Working with Raphael JS Library on Tizen”文章的“Adding transformations”一节描述了如何创建转换,以及如何将它应用于一个元素。 拖动事件的结果是将会应用转换。 你可以在./js/transforms.js 文件中找到所有绘制元素的移动,拖动开始,拖动结束对应的事件处理程序。

操作

由Raphael JS 提供的两个功能: Element.insertBefore() 和 Element.insertAfter()。 两者都负责排列元素。 所有新创建的Raphael元素都会保存到 elements[] 数组中,elements[0] 指的是最底部元素。

要在其他元素之前设置一个元素,使用 upElement() 函数:

var upElement = function(up) {
    if (up !== (elements.length - 1)) {
        // If selected item isn't on the peak: selected item insert up
        elements[up].insertAfter(elements[up + 1]);
        orderElements(up, up + 1);
    } else {
        tlib.logger.warn("up is not permitted");
    }
};

上 - 指elements[]数组中所选元素位置(索引)。 Element.insertAfter() 数将"elements[up]"元素插入到"elements[up+1]"之后。 函数的运行的可见效果如下所示:

同样,downElement() 函数也是这样工作的:

var downElement = function(down) {
    if (down !== 0) {
        // If selected item isn't on the bottom: selected item insert down
        elements[down].insertBefore(elements[down - 1]);
        orderElements(down - 1, down);
    } else {
        tlib.logger.warn("down is not permitted");
    }
};

OrderElements() 函数负责交换两个数组中元素的位置和设置一些其他属性。

var orderElements = function(up, down) {
    var tmp = elements[up];
    elements[up] = elements[down];
    elements[down] = tmp;

    if (elements[down].type === "image") {
        elements[down].refreshGlow();
    }

    elements[up].pos--;

    if (elements[up].type === "image") {
        elements[up].refreshGlow();
    }

    elements[down].pos++;
};
​

选择工具栏的“Clear”将触发调用 paper.clear() 函数,它将纸中所有元素删除掉。 它不使用任何参数。

工具栏的选项"Bask"将触发调用 removeElement() 函数:

/**
 * Removes text or image from the Raphael's paper
 */
var removeElement = function() {
    elements.splice(selectedItem.pos, 1);
    transforms.removeSelection(selectedItem);
    if (selectedItem.type === "image") {
        selectedItem.removeGlow();
    }
    selectedItem.remove();
    collage.setItemSelected(null);
};

上面的代码片段的最重要分是 Element.remove() 函数,它从纸中移除选定的元素。

 

摘要

我们希望这篇文章向您展示了如何在您的TIzen Web应用程序中使用Raphael JS 库。 你已经学习了如何将你的工作结果保存到文件中,这些在创建绘图应用程序、 拼贴、 智力游戏和更多应用中是很有用的。

在 Tizen 上使用Raphael JS 库创建令人惊叹的 Web 应用程序。

文件附件: