Emmanuil vor 4 Jahren
Ursprung
Commit
a1239955ca
11 geänderte Dateien mit 694 neuen und 0 gelöschten Zeilen
  1. 47 0
      js-13/index.html
  2. 50 0
      js-13/js.js
  3. 11 0
      js-14/index.html
  4. 49 0
      js-14/js.js
  5. 9 0
      js-15/hw.txt
  6. 30 0
      js-15/index.html
  7. 18 0
      js-15/js.js
  8. 5 0
      js-16/hw.txt
  9. 38 0
      js-16/index.html
  10. 385 0
      js-16/js.js
  11. 52 0
      js-16/style.css

+ 47 - 0
js-13/index.html

@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Document</title>
+    <style>
+      .trafficLight {
+        display: flex;
+        justify-content: center;
+      }
+      .color {
+        width: 300px;
+        height: 300px;
+        background: black;
+        border-radius: 50%;
+        margin: 20px;
+        color: white;
+        font-size: 40px;
+
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+      #btn {
+          width: 100%;
+          font-size: 30px;
+          color: green;
+          font-weight: bold;
+          border-radius: 50px;
+          border: 1px solid black;
+          cursor: pointer;
+      }
+    </style>
+  </head>
+  <body>
+    <div class="trafficLight">
+      <div class="green color"></div>
+      <div class="yellow color"></div>
+      <div class="red color"></div>
+    </div>
+
+    <button id="btn">FASTER</button>
+
+    <script src="js.js"></script>
+  </body>
+</html>

+ 50 - 0
js-13/js.js

@@ -0,0 +1,50 @@
+const delay = (ms) => new Promise((ok) => setTimeout(() => ok(ms), ms));
+
+async function trafficLight() {
+  while (true) {
+    const green = document.querySelector(".green");
+    const yellow = document.querySelector(".yellow");
+    const red = document.querySelector(".red");
+
+    green.style.background = "green";
+    red.style.background = "black";
+    var numGreen = 5;
+    const timerGreen = () => {
+      numGreen--;
+      numGreen === 0
+        ? (green.style.color = "black") && (red.style.color = "black")
+        : setTimeout(timerGreen, 1000) && (green.style.color = "white");
+      green.innerHTML = numGreen;
+    };
+    setTimeout(timerGreen, 1000);
+    await delay(5000); // включаем зеленый
+
+    green.style.background = "black";
+    yellow.style.background = "yellow";
+    var numYellow = 3;
+    const timerYellow = () => {
+      numYellow--;
+      numYellow === 0
+        ? (yellow.style.color = "black")
+        : setTimeout(timerYellow, 1000) && (yellow.style.color = "white");
+      yellow.innerHTML = numYellow;
+    };
+    setTimeout(timerYellow, 1000);
+    await delay(3000); // включаем желтый
+
+    yellow.style.background = "black";
+    red.style.background = "red";
+    var numRed = 7;
+    const timerRed = () => {
+      numRed--;
+      numRed === 0
+        ? (red.style.color = "black")
+        : setTimeout(timerRed, 1000) && (red.style.color = "white");
+      red.innerHTML = numRed;
+    };
+    setTimeout(timerRed, 1000);
+    await delay(7000) // включаем красный
+  }
+}
+
+trafficLight();

+ 11 - 0
js-14/index.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+</head>
+<body>
+    <script src="js.js"></script>
+</body>
+</html>

+ 49 - 0
js-14/js.js

@@ -0,0 +1,49 @@
+const delay = (ms) => new Promise((a) => setTimeout(() => a(ms), ms));
+
+async function speedtest(getPromise, count, parallel = 1) {
+  let startTime = performance.now();
+  let startQuery;
+  let endQuery;
+  let queryDurationAll = 0;
+
+  for (let i = 0; i < count; i++) {
+    let waiting = [];
+
+    for (let k = 0; k < parallel; k++) {
+      waiting.push(getPromise());
+    }
+    
+    startQuery = performance.now();
+    await Promise.all(waiting);
+    endQuery = performance.now();
+    queryDurationAll += endQuery - startQuery;
+  }
+  let finishTime = performance.now();
+
+  return {
+    //общую длительность работы цикла
+    duration: finishTime - startTime,
+
+    //реальное средняя скорость запроса
+    querySpeed: (count * parallel) / ((finishTime - startTime) * parallel),
+
+    //реальное среднее время запроса (отталкиваясь от count и времени работы цикла).
+    parallelDuration: queryDurationAll / (count * parallel),
+
+    //скорость в запросах в миллисекунду
+    parallelSpeed: (count * parallel) / (finishTime - startTime),
+
+    //среднее время обработки запроса параллельно (за какое время исполнилось parallel*count промисов)
+    queryDuration: ((endQuery - startQuery) / count) * parallel,
+  };
+}
+
+speedtest(() => delay(1000), 10, 10).then((result) => console.log(result));
+speedtest(
+  () =>
+    fetch("http://swapi.dev/api/people/1")
+      .then((res) => res.json())
+      .then((data) => console.log(data)),
+  10,
+  5
+).then((result) => console.log("swapi.dev: ", result));

+ 9 - 0
js-15/hw.txt

@@ -0,0 +1,9 @@
+сделать страницу на базе кода выше с:
+- канвасом
+- input type number для выбора размера/радиуса
+- input type color для выбора цвета.
+
+При рисовании, соответственно использовать значения этих инпутов для новых кружочков.
+Обратите внимание, что рисование происходит по клику, а клик это и нажатие, и отпускание кнопки. Это неудобно, исправьте это, используя onmousemove и проверку на нажатые кнопки мыши (используйте свойство buttons объекта события, переданного в обработчик)
+
+Так же можете поэкспериментировать с другими графическими примитивами типа линий/прямоугольников

+ 30 - 0
js-15/index.html

@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Document</title>
+    <style>
+      input {
+        width: 100%;
+        margin-top: 5px;
+      }
+      #size {
+        font-size: 20px;
+      }
+    </style>
+ </head>
+  <body>
+    <canvas
+      id="myCanvas"
+      width="400"
+      height="150"
+      style="border: 1px solid #d3d3d3;"
+    >
+      Your browser does not support the HTML5 canvas tag.</canvas
+    >
+    <input id="size" type="number" value="10">
+    <input id="color" type="color">
+    <script src="js.js"></script>
+  </body>
+</html>

+ 18 - 0
js-15/js.js

@@ -0,0 +1,18 @@
+var c = document.getElementById("myCanvas");
+var ctx = c.getContext("2d");
+
+let selection = [];
+
+color.onchange = () => {
+  selection.forEach((c) => (c.color = color.value));
+};
+
+c.onmousemove = ({ clientX, clientY, buttons }) => {
+  if (buttons > 0) {
+    ctx.fillStyle = color.value;
+    ctx.beginPath();
+    ctx.arc(clientX, clientY, size.value, 0, Math.PI * 2);
+    ctx.closePath();
+    ctx.fill();
+  }
+};

+ 5 - 0
js-16/hw.txt

@@ -0,0 +1,5 @@
+ДЗ:
+доделать на базе кода с занятия:
+1) отправку картинки в чат используя canvas.toDataURL и jsonPost
+2) инструмент эллипса по аналогии с Rectangle и Line
+3) инструмент прямоугольного выделения, который будет позволять выделять элементы на экране прямоугольником. используйте inBounds для кружочка и допишите inBounds для остальных классов

+ 38 - 0
js-16/index.html

@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width" />
+    <title>eval</title>
+    <link href="style.css" rel="stylesheet" type="text/css" />
+    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.3/papaparse.min.js"></script>
+    <script src="http://gitlab.a-level.com.ua/gitgod/nanobind/raw/master/static/nb.js"></script>
+  </head>
+  <body>
+    <canvas id="canvas" width="600" height="200"></canvas>
+    <button id="undo">UNDO</button>
+    <input type="color" id="color" />
+
+    <select id="tool">
+      <option value="graffity">Graffity</option>
+      <option value="circle">Circle</option>
+      <option value="line">Line</option>
+      <option value="rectangle">Rectangle</option>
+      <option value="ellipse">Ellipse</option>
+      <option value="select">Select</option>
+    </select>
+
+    <label id="checkbox"> <input type="checkbox" id="fill" />Fill </label>
+    <input type="number" id="size" value="10" />
+    <button id="delete">Delete...</button>
+
+    <div id="chat">
+      <input id="nick" type="nick" placeholder="nick" />
+      <input id="message" type="message" placeholder="ссылку вставлять не нужно, просто нарисуй и нажми отправить" />
+      <button id="sendInChat">Send</button>
+    </div>
+
+    <script src="js.js"></script>
+  </body>
+</html>

+ 385 - 0
js-16/js.js

@@ -0,0 +1,385 @@
+const canvas = document.getElementById("canvas");
+const ctx = canvas.getContext("2d");
+
+const width = canvas.width;
+const height = canvas.height;
+
+let current;
+let selection = [];
+
+const tools = {
+  graffity: {
+    mousemove(e) {
+      e.buttons & 1 &&
+        new Circle(
+          e.clientX,
+          e.clientY,
+          +size.value,
+          color.value,
+          fill.checked
+        );
+    },
+  },
+  circle: {
+    mousedown(e) {
+      current = new Circle(e.clientX, e.clientY, 1, color.value, fill.checked);
+    },
+    mousemove(e) {
+      if (!current) return;
+
+      current.radius = current.distanceTo(e.clientX, e.clientY);
+      Drawable.drawAll();
+    },
+
+    mouseup(e) {
+      current = null;
+    },
+  },
+  line: {
+    mousedown(e) {
+      current = new Line(e.clientX, e.clientY, 0, 0, color.value, +size.value);
+    },
+    mousemove(e) {
+      if (!current) return;
+
+      current.width = e.clientX - current.x;
+      current.height = e.clientY - current.y;
+
+      Drawable.drawAll();
+    },
+
+    mouseup(e) {
+      current = null;
+    },
+  },
+
+  rectangle: {
+    mousedown(e) {
+      current = new Rectangle(
+        e.clientX,
+        e.clientY,
+        0,
+        0,
+        color.value,
+        +size.value,
+        fill.checked
+      );
+    },
+    mousemove(e) {
+      if (!current) return;
+      current.width = e.clientX - current.x;
+      current.height = e.clientY - current.y;
+      Drawable.drawAll();
+    },
+
+    mouseup(e) {
+      current = null;
+    },
+  },
+
+  ellipse: {
+    mousedown(e) {
+      current = new Ellipse(
+        e.clientX,
+        e.clientY,
+        0,
+        0,
+        color.value,
+        +size.value,
+        fill.checked
+      );
+    },
+    mousemove(e) {
+      if (!current) return;
+      current.width = e.clientX - current.x;
+      current.height = e.clientY - current.y;
+      Drawable.drawAll();
+    },
+
+    mouseup(e) {
+      current = null;
+    },
+  },
+
+  select: {
+    click(e) {
+      console.log(e);
+      let found = Drawable.instances.filter(
+        (c) => c.in && c.in(e.clientX, e.clientY)
+      );
+      if (found.length) {
+        if (e.ctrlKey) {
+          selection.push(found.pop());
+        } else {
+          selection = [found.pop()];
+        }
+      } else {
+        if (!e.ctrlKey) selection = [];
+      }
+
+      Drawable.drawAll(selection);
+    },
+  },
+};
+
+function superHandler(evt) {
+  let t = tools[tool.value];
+  if (typeof t[evt.type] === "function") t[evt.type].call(this, evt);
+}
+
+canvas.onmousemove = superHandler;
+canvas.onmouseup = superHandler;
+canvas.onmousedown = superHandler;
+canvas.onclick = superHandler;
+
+////
+
+function Drawable() {
+  Drawable.addInstance(this);
+}
+
+const distance = (x1, y1, x2, y2) => ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5;
+
+Drawable.prototype.draw = function () {};
+Drawable.prototype.distanceTo = function (x, y) {
+  if (typeof this.x !== "number" || typeof this.y !== "number") {
+    return NaN;
+  }
+  return distance(this.x, this.y, x, y);
+};
+Drawable.instances = [];
+Drawable.addInstance = function (item) {
+  Drawable.instances.push(item);
+};
+
+Drawable.drawAll = function (selection = []) {
+  ctx.clearRect(0, 0, width, height);
+  Drawable.forAll((item) => item.draw(selection.includes(item)));
+};
+
+Drawable.forAll = function (callback) {
+  for (var i = 0; i < Drawable.instances.length; i++) {
+    callback(Drawable.instances[i]);
+  }
+};
+
+class Circle extends Drawable {
+  constructor(x, y, radius, color, fill) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.radius = radius;
+    this.color = color;
+    this.fill = fill;
+    this.draw();
+  }
+
+  draw(selected) {
+    ctx.beginPath();
+    ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
+    ctx.closePath();
+    ctx.fillStyle = this.color;
+    if (selected) {
+      ctx.setLineDash([5, 15]);
+      ctx.lineWidth = 2;
+      ctx.stroke();
+    } else ctx.setLineDash([]);
+    if (this.fill) ctx.fill();
+    else ctx.stroke();
+  }
+
+  in(x, y) {
+    return this.distanceTo(x, y) < this.radius;
+  }
+
+  inBounds(x, y, w, h) {
+    return this.x >= x && this.x <= x + w && this.y >= y && this.y <= y + h;
+  }
+}
+
+class Line extends Drawable {
+  constructor(x, y, width, height, color, lineWidth) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+    this.color = color;
+    this.lineWidth = lineWidth;
+
+    this.draw();
+  }
+
+  draw(selected) {
+    ctx.beginPath();
+    ctx.moveTo(this.x, this.y);
+    ctx.lineTo(this.x + this.width, this.y + this.height);
+    ctx.closePath();
+    ctx.strokeStyle = this.color;
+    ctx.lineWidth = this.lineWidth;
+    ctx.stroke();
+
+    if (selected) {
+      ctx.setLineDash([5, 15]);
+      ctx.lineWidth = 4;
+      ctx.stroke();
+    } else ctx.setLineDash([]);
+
+    if (this.fill) ctx.fill();
+    else {
+      ctx.strokeStyle = this.color;
+      ctx.stroke();
+    }
+  }
+
+  in(x, y) {
+    return (
+      x > this.x &&
+      x < this.x + this.width &&
+      y > this.y &&
+      y < this.y + this.height
+    );
+  }
+}
+
+class Rectangle extends Drawable {
+  constructor(x, y, width, height, color, lineWidth, fill) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+    this.color = color;
+    this.lineWidth = lineWidth;
+    this.fill = fill;
+
+    this.draw();
+  }
+
+  draw(selected) {
+    if (!selected) {
+      ctx.setLineDash([]);
+
+      if (this.fill) {
+        ctx.fillStyle = this.color;
+        ctx.fillRect(this.x, this.y, this.width, this.height);
+      } else {
+        ctx.beginPath();
+        ctx.lineWidth = this.lineWidth;
+        ctx.strokeStyle = this.color;
+        ctx.rect(this.x, this.y, this.width, this.height);
+        ctx.stroke();
+      }
+    } else {
+      ctx.setLineDash([5, 15]);
+      ctx.beginPath();
+      ctx.lineWidth = this.lineWidth;
+      ctx.strokeStyle = this.color;
+      ctx.rect(this.x, this.y, this.width, this.height);
+      ctx.stroke();
+    }
+  }
+
+  in(x, y) {
+    return (
+      x > this.x &&
+      x < this.x + this.width &&
+      y > this.y &&
+      y < this.y + this.height
+    );
+  }
+}
+
+class Ellipse extends Drawable {
+  constructor(x, y, width, height, color, lineWidth, fill) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+    this.color = color;
+    this.lineWidth = lineWidth;
+    this.fill = fill;
+
+    this.draw();
+  }
+
+  draw(selected) {
+    const width2 = this.width / 2;
+    const height2 = this.height / 2;
+
+    ctx.beginPath();
+    ctx.ellipse(
+      this.x + width2,
+      this.y + height2,
+      Math.abs(width2),
+      Math.abs(height2),
+      0,
+      0,
+      2 * Math.PI
+    );
+    ctx.closePath();
+    ctx.fillStyle = this.color;
+
+    if (selected) {
+      ctx.setLineDash([5, 15]);
+      ctx.lineWidth = 4;
+      ctx.stroke();
+    } else ctx.setLineDash([]);
+
+    if (this.fill) ctx.fill();
+    else {
+      ctx.strokeStyle = this.color;
+      ctx.stroke();
+    }
+  }
+
+  in(x, y) {
+    return (
+      x > this.x &&
+      x < this.x + this.width &&
+      y > this.y &&
+      y < this.y + this.height
+    );
+  }
+}
+
+color.onchange = () => {
+  selection.forEach((c) => (c.color = color.value));
+  Drawable.drawAll(selection);
+};
+
+document.getElementById("delete").onclick = () => {
+  Drawable.instances = Drawable.instances.filter(
+    (item) => !selection.includes(item)
+  );
+  selection = [];
+  Drawable.drawAll();
+};
+
+function jsonPost(url, data) {
+  return new Promise((resolve, reject) => {
+    var x = new XMLHttpRequest();
+    x.onerror = () => reject(new Error("jsonPost failed"));
+    x.open("POST", url, true);
+    x.send(JSON.stringify(data));
+
+    x.onreadystatechange = () => {
+      if (x.readyState == XMLHttpRequest.DONE && x.status == 200) {
+        resolve(JSON.parse(x.responseText));
+      } else if (x.status != 200) {
+        reject(new Error("status is not 200"));
+      }
+    };
+  });
+}
+
+sendInChat.onclick = () => {
+  jsonPost("http://students.a-level.com.ua:10012", {
+    func: "addMessage",
+    nick: nick.value,
+    message: `<img src = ${canvas.toDataURL()} >`,
+  }).then(() => {
+    console.log(imgSrcUrl5);
+  });
+};

+ 52 - 0
js-16/style.css

@@ -0,0 +1,52 @@
+* {
+  box-sizing: border-box;
+  margin: 0;
+  padding: 0;
+}
+
+body {
+  margin: 0;
+  padding: 0;
+}
+
+button {
+  width: 100%;
+  font-size: 2em;
+}
+input,
+button,
+select {
+  width: 100%;
+  font-size: 2em;
+}
+
+table {
+  border: 1px;
+  border-collapse: collapse;
+}
+
+#checkbox {
+  display: flex;
+  justify-content: center;
+  font-size: 30px;
+  font-weight: bold; 
+}
+
+#fill {
+  transform: scale(2);
+  cursor: pointer;
+  width: 50px;
+  margin-top: 11px;
+}
+
+td,
+th {
+  border: 1px solid black;
+}
+
+#chat {
+  padding-top: 20px;
+}
+/*div#content {*/
+/*display: none;*/
+/*}*/