Принцип копирования — различия между версиями
Wikiadmin (обсуждение | вклад) м (Замена текста — «<source lang="(.*)" first-line="(.*)">» на «<syntaxhighlight lang="$1" line start="$2" enclose="div">») |
Денис (обсуждение | вклад) |
||
(не показаны 3 промежуточные версии 1 участника) | |||
Строка 6: | Строка 6: | ||
<syntaxhighlight lang="javascript" line start="1" enclose="div"> | <syntaxhighlight lang="javascript" line start="1" enclose="div"> | ||
var buffer = document.createElement('canvas'); | var buffer = document.createElement('canvas'); | ||
− | </ | + | </syntaxhighlight> |
Далее нарисуем в "buffer" изображение, которое хотим копировать: | Далее нарисуем в "buffer" изображение, которое хотим копировать: | ||
Строка 12: | Строка 12: | ||
var buf_ctx = buffer.getContext('2d'); | var buf_ctx = buffer.getContext('2d'); | ||
buf_ctx... // здесь рисуется нужное нам изображение | buf_ctx... // здесь рисуется нужное нам изображение | ||
− | </ | + | </syntaxhighlight> |
Чтобы скопировать полученное изображение из внутренней памяти на экран, воспользуемся функцией drawImage(): | Чтобы скопировать полученное изображение из внутренней памяти на экран, воспользуемся функцией drawImage(): | ||
<syntaxhighlight lang="javascript" line start="1" enclose="div"> | <syntaxhighlight lang="javascript" line start="1" enclose="div"> | ||
context.drawImage(buffer, x, y); | context.drawImage(buffer, x, y); | ||
− | </ | + | </syntaxhighlight> |
где "x", "y" - координаты, в которые копируется изображение. | где "x", "y" - координаты, в которые копируется изображение. | ||
Строка 28: | Строка 28: | ||
Скачать программу: [[Медиа:CopyPic_v1_release.zip|CopyPic_v1_release.zip]] | Скачать программу: [[Медиа:CopyPic_v1_release.zip|CopyPic_v1_release.zip]] | ||
− | Текст программы на языке JavaScript (разработчик [[Цветков Денис]]): < | + | <div class="mw-collapsible mw-collapsed" style="width:100%" > |
+ | '''Текст программы на языке JavaScript (разработчик [[Цветков Денис]]):''' <div class="mw-collapsible-content"> | ||
Файл '''"CopyPic_v1_release.js"''' | Файл '''"CopyPic_v1_release.js"''' | ||
<syntaxhighlight lang="javascript" line start="1" enclose="div"> | <syntaxhighlight lang="javascript" line start="1" enclose="div"> | ||
Строка 190: | Строка 191: | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
Файл '''"CopyPic_v1_release.html"''' | Файл '''"CopyPic_v1_release.html"''' | ||
− | <syntaxhighlight lang=" | + | <syntaxhighlight lang="html5" line start="1" enclose="div"> |
<!DOCTYPE html> | <!DOCTYPE html> | ||
<html> | <html> | ||
Строка 206: | Строка 207: | ||
</body> | </body> | ||
</html> | </html> | ||
− | </ | + | </syntaxhighlight> |
− | </ | + | </div> |
+ | </div> | ||
[[Category: Виртуальная лаборатория]] | [[Category: Виртуальная лаборатория]] |
Текущая версия на 09:24, 11 марта 2015
Виртуальная лаборатория > Принцип копированияЕсли какое либо сгенерированное изображение в программе повторяется много раз, то имеет смысл не рисовать его каждый раз заново, а копировать единожды нарисованное. Это позволит в несколько раз увеличить скорость работы программы. Далее будет продемонстрировано применение данного принципа при рисовании на HTML5 Canvas с помощью Javascript.
Для начала создадим новый элемент Canvas - "buffer". Он будет находиться во внутренней памяти программы, без вывода на экран.
1 var buffer = document.createElement('canvas');
Далее нарисуем в "buffer" изображение, которое хотим копировать:
1 var buf_ctx = buffer.getContext('2d');
2 buf_ctx... // здесь рисуется нужное нам изображение
Чтобы скопировать полученное изображение из внутренней памяти на экран, воспользуемся функцией drawImage():
1 context.drawImage(buffer, x, y);
где "x", "y" - координаты, в которые копируется изображение.
В программе ниже демонстрируется применение описанного принципа. В фукнции draw_star(color) генерируется изображение звезды с градиентом, color - цвет звезды. Функция generate_star_pics() с помощью draw_star(color) генерирует два различных типа звезд - фиолетовые (название буфера - stars1) и желтые (stars2).
После задается треугольная решетка, и запускается цикл setInterval(tick, 1000 / fps), который рассчитывает изменение положения узлов в решетке, и запускает функцию рисования системы - draw(). Данная функция копирует изображение звезды определенного цвета (определяемого параметром type) в нужные позиции.
Скачать программу: CopyPic_v1_release.zip
Файл "CopyPic_v1_release.js"
1 function Main_Copy_pic(canvas) {
2
3 canvas.onselectstart = function () {return false;}; // запрет выделения canvas
4
5 // Предварительные установки
6
7 var context = canvas.getContext("2d"); // на context происходит рисование
8
9 var a0 = 1; // масштаб расстояния
10
11 // *** Задание вычислительных параметров ***
12
13 var a = 2 * a0; // шаг решетки
14 var N = 8.46 * a; // количество звезд по горизонтали
15
16 // *** Выполнение программы ***
17
18 var fps = 60; // количество кадров в секунду
19 var scale = canvas.height / N; // масштабный коэффициент для перехода от расчетных к экранным координатам
20 var w = canvas.width / scale; // ширина окна в расчетных координатах
21 var h = canvas.height / scale; // высота окна в расчетных координатах
22
23 var points = [];
24 var ax = a; // шаг по горизонтали
25 var ay = a * Math.sqrt(3) / 2; // шаг по вертикали
26
27 function set_triangular_lattice() { // треугольная решетка
28 for (var i = 0; i < Math.floor(w / ax) + 5; i++) {
29 points[i] = [];
30 for (var j = 0; j < Math.floor(h / ay) + 5; j++) {
31 points[i][j] = [];
32 points[i][j].x = (i - 2) * ax * scale + ax / 2 * (j % 2) * scale;
33 points[i][j].y = (j - 2) * ay * scale;
34 points[i][j].type = j % 2;
35 }
36 }
37 }
38
39 // Предварительная генерация двух разных звезд
40 var stars1, stars2;
41 function generate_star_pics() {
42 stars1 = draw_star("#8050cc"); // фиолетовые звезды
43 stars2 = draw_star("#dd9922"); // желтые звезды
44 }
45 function draw_star(color) {
46 var buffer = document.createElement('canvas');
47 var ctx = buffer.getContext('2d');
48
49 var n = 5; // углов у звезды
50 var r = 0.35 * a * scale; // радиус звезды
51 var fi = 0; // поворот звезды
52
53 // здесь звезда рисуется на невидимый канвас, с которого потом будет копироваться на видимый
54 ctx.beginPath();
55 for(var i = 0; i <= (n * 2) + 1; i++) {
56 var r_actual = r * (i % 2 + 1) / 2;
57 var omega = 2 * Math.PI / (n * 2) * i;
58 ctx.lineTo(((r_actual * Math.sin(omega + fi * 3.14 / 180)) + r), (r_actual * Math.cos(omega + fi * 3.14 / 180)) + r);
59 }
60 ctx.closePath();
61 var gradient = context.createRadialGradient(r, r, r, r, r, 0);
62 gradient.addColorStop(0, color);
63 gradient.addColorStop(1, color_light(color));
64 ctx.fillStyle = gradient;
65 ctx.fill();
66
67 return buffer;
68 }
69 function color_light(col) { // осветление цвета для градиента, можно еще делать через схему HSV -> RGB
70 var col_light = "#";
71 for (var i = 1; i < col.length; i++) {
72 if (parseInt(col[i], 16) + 0x8 <= 0xf) col_light += (parseInt(col[i], 16) + 0x8).toString(16);
73 else col_light += "f";
74 }
75 return col_light;
76 }
77
78 function tick() {
79 move();
80 draw();
81 }
82
83 var phase1, phase2, phase3;
84 var phase1_0 = 60, phase2_0 = 60, phase3_0 = 60;
85 function init() {
86 set_triangular_lattice();
87 phase1 = phase1_0;
88 phase2 = phase2_0;
89 phase3 = phase3_0;
90 }
91 function move() { // перемещение звезд
92 var i, j, sign, p;
93 if (phase1 > 0) {
94 for (i = 0; i < points.length; i++)
95 for (j = 0; j < points[i].length; j++) {
96 if (j % 2 == 0) sign = 1;
97 else sign = -1;
98 points[i][j].x = points[i][j].x + sign * ax * scale / phase1_0;
99 }
100 phase1--;
101 } else if (phase2 > 0) {
102 p = 1;
103 for (j = 0; j < points[0].length; j++) {
104 for (i = 0; i < points.length; i++) {
105 if (p >= 2) {
106 if (i % 2 == 0) sign = 1;
107 else sign = -1;
108 } else {
109 if (i % 2 == 1) sign = 1;
110 else sign = -1;
111 }
112 points[i][j].x = points[i][j].x + sign * ax * scale / (phase2_0 * 2);
113 points[i][j].y = points[i][j].y - sign * ay * scale / phase2_0;
114 }
115 if (p == 3) p = 0;
116 else p++;
117 }
118 phase2--;
119 } else if (phase3 > 0) {
120 p = 0;
121 for (j = 0; j < points[0].length; j++) {
122 for (i = 0; i < points.length; i++) {
123 if (p >= 2) {
124 if (i % 2 == 0) sign = 1;
125 else sign = -1;
126 } else {
127 if (i % 2 == 1) sign = 1;
128 else sign = -1;
129 }
130 points[i][j].x = points[i][j].x + sign * ax * scale / (phase3_0 * 2);
131 points[i][j].y = points[i][j].y + sign * ay * scale / phase3_0;
132 }
133 if (p == 3) p = 0;
134 else p++;
135 }
136 phase3--;
137 } else {init()}
138 }
139
140 // Рисование
141 function draw() {
142 // очистка экрана
143 context.fillStyle = "#000000";
144 context.fillRect(0, 0, w * scale, h * scale);
145
146 // копирование звезд в нужные позиции
147 for (var i = 0; i < points.length; i++)
148 for (var j = 0; j < points[i].length; j++) {
149 if (points[i][j].type == 0) context.drawImage(stars1, points[i][j].x, points[i][j].y);
150 else context.drawImage(stars2, points[i][j].x, points[i][j].y);
151 }
152 // звезда не рисуется в цикле каждый раз, когда нужна, она просто копируется в нужную точку.
153 }
154
155 generate_star_pics(); // генерация изображений звезд происходит только один раз
156 init();
157 setInterval(tick, 1000 / fps);
158
159 }
Файл "CopyPic_v1_release.html"
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8" />
5 <title>Copy pic</title>
6 <script src="CopyPic_v1_release.js"></script>
7 </head>
8 <body>
9 <canvas id="Copy_pic_canvas" width="500" height="500" style="border:1px solid #000000;"></canvas>
10
11 <script type="text/javascript">var app = new Main_Copy_pic(document.getElementById('Copy_pic_canvas'));</script>
12 </body>
13 </html>