{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "title: p5.js教程04-平移-旋转-缩放\n", "date: 2018-06-06 20:17:55\n", "tags: [p5.js]\n", "toc: true\n", "xiongzhang: true\n", "\n", "\n", "---\n", "\n", "\n", "\n", "> 声明: 本文由[DataScience](http://mlln.cn)发表,未经允许不得转载。 转载请注明[本文链接](http://mlln.cn)mlln.cn, 并在文后留言`转载`.\n", "\n", "本文代码运行环境:\n", "\n", "- windows10\n", "- jupyter notebook\n", "- p5.js 0.6.1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 概述\n", "\n", "用于在屏幕上定位和移动物体的替代技术是改变屏幕坐标系。例如,您可以向右移动50个像素的形状,或者可以将坐标(0,0)的位置向右移动50个像素 - 屏幕上的可视结果是相同的。通过修改默认坐标系,我们可以创建不同的变换,包括平移,旋转和缩放。\n", "\n", "(下面我们注册p5魔法, 以便于在jupyter notebook中使用p5.js, 如果你不用notebook, 请忽略这部分python代码)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "from IPython.core.magic import register_cell_magic\n", "from IPython.display import IFrame\n", "\n", "TEMPLATE = \"\"\"\n", "\n", "\n", "\n", "\n", "\n", "\n", "Notebook中显示P5.js页面\n", "\n", "\n", "
p5.js效果展示: %(name)s
\n", "\n", "\n", "\n", "\"\"\"\n", "\n", "\n", "@register_cell_magic\n", "def p5(line, cell):\n", " file_id, kws = line.split(' ')[0], line.split(' ')[1:]\n", " kwargs = {}\n", " for kw in kws:\n", " k, v = kw.split('=')\n", " kwargs[k] = v\n", " filename = f\"p5js-html/p5-04-{file_id}.html\"\n", " with open(filename, \"w\", encoding='utf8') as fp:\n", " fp.write(TEMPLATE % {\"script\": cell, \"name\": filename})\n", " if 'height' not in kwargs:\n", " kwargs['height'] = '200px'\n", " return IFrame(filename, width=\"100%\", **kwargs)\n", "\n", "del p5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 平移\n", "\n", "实现这个效果: translate()函数将屏幕的(0,0)坐标设置为鼠标位置(mouseX和mouseY)。每次draw()函数执行时,ellipse()都会在新的坐标系中绘制。看下面的代码, 每次都会调用ellipse(0, 0, 30, 30), 也就是都在(0, 0)的位置绘制矩形, 但是因为坐标系的变换, (0, 0)位置总是在鼠标的位置, 所以下面代码意义就是在鼠标所在位置绘制圆形。" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%p5 translate height=250\n", "\n", "function setup() { \n", " createCanvas(220, 220); \n", " background(204); \n", "}\n", "\n", "function draw() { \n", " translate(mouseX, mouseY); \n", " ellipse(0, 0, 20, 20); \n", "}\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%p5 folow-mouse height=250\n", "\n", "function setup() { \n", " createCanvas(220, 220); \n", " background(204); \n", "}\n", "\n", "function draw() { \n", " ellipse(mouseX, mouseY, 20, 20); \n", "}\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 旋转坐标系\n", "\n", "rotate()函数旋转坐标系。它有一个参数,即旋转的角度(弧度)。它始终相对于坐标原点(0,0)旋转,称为围绕原点旋转。" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%p5 rotate height=250\n", "\n", "function setup() { \n", " createCanvas(220, 220); \n", " background(204); \n", "}\n", "\n", "let r= 0;\n", "function draw() { \n", " rotate(r)\n", " r += PI/4 * 0.01\n", " ellipse(100, 100, 20, 20); \n", " if (r > PI/4){\n", " r = - PI / 4\n", " background(204); \n", " }\n", " \n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 缩放\n", "\n", "scale()函数拉伸画布上的坐标。由于坐标随着比例的变化而扩展或收缩,因此绘制到画布的所有内容的尺寸都会增大或减小。比例写为十进制百分比。因此,参数1.5 to scale()为150%,3为300%。" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%p5 scale height=250\n", "\n", "function setup() { \n", " createCanvas(220, 220); \n", " background(204); \n", "}\n", "\n", "let r= 0.1;\n", "function draw() { \n", " scale(r)\n", " // 每次迭代增加0.01\n", " r += 0.01\n", " ellipse(100, 100, 20, 20);\n", " // 如果超过一定值, 就重置r\n", " if (r>2){\n", " background(204); \n", " r=0.1\n", " }\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Push and Pop \n", "\n", "要隔离转换的影响,使它们不影响以后的图形,请使用push()和pop()函数。当push()运行时,它会保存当前坐标系的副本,然后在pop()之后恢复该系统。当一个形状需要变换但另一个变形不需要变换时,这很有用。" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%p5 push-pop height=250\n", "\n", "function setup() { \n", " createCanvas(220, 220); \n", " background(204); \n", "}\n", "\n", "let r= 0.1;\n", "function draw() {\n", " push()\n", " scale(r)\n", " // 每次迭代增加0.01\n", " r += 0.01\n", " ellipse(100, 100, 20, 20);\n", " // 如果超过一定值, 就重置r\n", " if (r>2){\n", " background(204); \n", " r=0.1\n", " }\n", " pop()\n", " // 保证不缩放矩形\n", " rect(220-r*80, r*80, 10, 10)\n", "}" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }