generated from mirzaev/pot-php
Compare commits
11 Commits
1.0.0
...
0f09b2de71
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f09b2de71 | |||
| 3ef75a5814 | |||
| 4d2e419018 | |||
| 91d5883885 | |||
| 4203b1e9f8 | |||
| 658a95877c | |||
| 3ce62f13e2 | |||
| 1361f8cd5e | |||
| 323beeb886 | |||
| 9378f022b4 | |||
| 51e8214cd2 |
53
README.md
53
README.md
@@ -1,2 +1,51 @@
|
||||
# pechatalka
|
||||
Chat-robot constructor for the Svoboda typography
|
||||
# Pechatalka
|
||||
Site and chat-robot constructor for the Svoboda typography
|
||||
|
||||
# Installation
|
||||
Before process any command think about **what it does** and whether the **paths** are specified correctly<br>
|
||||
|
||||
## NGINX
|
||||
### Create the NGINX server
|
||||
You can copy an example of the server file from here: `/examples/nginx/pechatalka.conf`<br>
|
||||
<small><i>I prefer to rename nginx config files to domain names. For example: `pechatalka.kodorvan.tech`</i></small><br>
|
||||
|
||||
<i>The file will be half commented out specifically to start the server for generating the TLS/SSL certificate</i><br>
|
||||
|
||||
1. `cd /examples/nginx`<br>
|
||||
2. `sudo cp pechatalka.conf /etc/nginx/sites-avaiable/pechatalka.conf`<br>
|
||||
3. `sudo nvim /etc/nginx/sites-avaiable/pechatalka.conf`<br>
|
||||
<small>3.1. <i>Customize the file according to your requirements</i></small><br>
|
||||
4. `sudo ln -s /etc/nginx/sites-avaiable/pechatalka.conf /etc/nginx/sites-enabled/pechatalka.conf`<br>
|
||||
5. `sudo nginx -t`<br>
|
||||
<small>5.1. <i>Make sure that <b>NGINX does not throw errors</b>, otherwise proceed to the instructions for generate a TLS/SSL certificate</i></small><br>
|
||||
6. `sudo service nginx restart`<br>
|
||||
|
||||
### Add mime-type recognition for javascript modules
|
||||
<small>Edit the file: `/etc/nginx/mime.types`</small><br>
|
||||
**From:** `application/javascript js;`<br>
|
||||
**To:** `application/javascript js mjs;`
|
||||
|
||||
### Generate a TLS/SSL sertificate (via [certbot](http://certbot.eff.org/) for [ubuntu](https://ubuntu.com/))
|
||||
1. `sudo apt install certbot python3-certbot-nginx`<br>
|
||||
2. `sudo certbot certonly --nginx`<br>
|
||||
<small><i>The **domain** must already be **bound** to the **IP-address** of the server by `CNAME`, `A` or `AAAA` record</i></small><br>
|
||||
3. Uncomment and reconfigure the nginx server file
|
||||
4. `sudo nginx -t`<br>
|
||||
<small>4.1. <i>Make sure that <b>NGINX does not throw errors</b></i></small><br>
|
||||
5. `sudo service nginx restart`
|
||||
|
||||
### Set up firewall rules for HTTP and HTTPS requests (for [ubuntu](https://ubuntu.com/))
|
||||
1. `sudo ufw allow "NGINX Full"`<br>
|
||||
<small>1.1. <i>Make sure that the <b>port for SSH connection</b> is open</i></small><br>
|
||||
2. `sudo ufw allow 22`<br>
|
||||
<small>2.1. <i>Use your SSH port instead of 22</i></small><br>
|
||||
3. `sudo ufw enable`
|
||||
|
||||
## SystemD (or any alternative you like)
|
||||
You can copy an example of the systemd file from here: `/examples/systemd/arming.service`<br>
|
||||
1. `cd examples/systemd`<br>
|
||||
2. `sudo cp pechatalka.service /etc/systemd/system/pechatalka.service && sudo chmod +x /etc/systemd/system/pechatalka.service`<br>
|
||||
3. `sudo nvim /etc/systemd/system/pechatalka.service`<br>
|
||||
<small>3.1. <i>Customize the file according to your requirements</i></small><br>
|
||||
4. `sudo systemctl daemon-reload`<br>
|
||||
3. `sudo systemctl enable pechatalka`<br>
|
||||
Submodule pechatalka.mjs updated: c94542bfd3...4496b0464b
@@ -8,7 +8,9 @@ namespace svoboda\pechatalka\controllers;
|
||||
use svoboda\pechatalka\controllers\core,
|
||||
svoboda\pechatalka\models\paper,
|
||||
svoboda\pechatalka\models\product,
|
||||
svoboda\pechatalka\models\enumerations\products\type as product_type;
|
||||
/* svoboda\pechatalka\models\enumerations\paper\type as paper_type, */
|
||||
svoboda\pechatalka\models\enumerations\paper\format as paper_format,
|
||||
svoboda\pechatalka\models\enumerations\product\type as product_type;
|
||||
|
||||
// Framework for PHP
|
||||
use mirzaev\minimal\http\enumerations\content,
|
||||
@@ -194,7 +196,14 @@ final class generator extends core
|
||||
if ($type === product_type::pin_37) {
|
||||
// Pin 37mm
|
||||
|
||||
$biba = paper::a5(type: $type, products: $products, canvas: $canvas);
|
||||
$biba = paper::generate(
|
||||
format: paper_format::a6,
|
||||
type: $type,
|
||||
products: $products,
|
||||
canvas: $canvas,
|
||||
dpi: 80,
|
||||
fit: true
|
||||
);
|
||||
}
|
||||
|
||||
if (str_contains($this->request->headers['accept'], content::any->value)) {
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models\enumerations\paper;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\enumerations\product\type as product_type;
|
||||
|
||||
/**
|
||||
* Types of products
|
||||
*
|
||||
* @package svoboda\pechatalka\models\enumerations\paper
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
enum format
|
||||
{
|
||||
case a6;
|
||||
|
||||
/**
|
||||
* Dimensions
|
||||
*
|
||||
* @return array The paper format dimensions in centimeters (cm) ['width', 'height']
|
||||
*/
|
||||
public function dimensions(): array
|
||||
{
|
||||
return match ($this) {
|
||||
format::a6 => [
|
||||
'width' => 10.5,
|
||||
'height' => 14.8
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Places
|
||||
*
|
||||
* @param product_type $type The product type
|
||||
* @param int|float $padding The paper padding (print borders)
|
||||
*
|
||||
* @return array The paper places by the product type in centimeters (cm)
|
||||
*/
|
||||
public function places(product_type $type, int|float $padding = 0): array|false
|
||||
{
|
||||
if ($this === format::a6) {
|
||||
// A6
|
||||
|
||||
// Initializing the paper dimensions
|
||||
$paper = $this->dimensions();
|
||||
|
||||
if ($type === product_type::pin_37) {
|
||||
// Pin 37mm
|
||||
|
||||
// Initializing the product dimensions
|
||||
$blank = $type->areas()['blank'];
|
||||
|
||||
// Calculating the general X coordinate
|
||||
$x = $paper['width'] / 2 - $blank['width'] / 2 - $padding;
|
||||
|
||||
// Initializing the amount of products
|
||||
$amount = 2;
|
||||
|
||||
// Calculating the summary products height
|
||||
$height = $blank['height'] * $amount;
|
||||
|
||||
// Calculating the free space on the page
|
||||
$free = $paper['height'] - $padding * 2 - $height;
|
||||
|
||||
// Calculating the offset between products and from products to the paper borders
|
||||
$offset = $free / ($amount + 1);
|
||||
|
||||
// Exit (success)
|
||||
return [
|
||||
[
|
||||
'x' => $x,
|
||||
'y' => $offset
|
||||
],
|
||||
[
|
||||
'x' => $x,
|
||||
'y' => $offset + $blank['height'] + $offset
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models\enumerations\products;
|
||||
namespace svoboda\pechatalka\models\enumerations\product;
|
||||
|
||||
/**
|
||||
* Types of products
|
||||
*
|
||||
* @package svoboda\pechatalka\models\enumerations\products
|
||||
* @package svoboda\pechatalka\models\enumerations\product
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
@@ -19,19 +19,19 @@ enum type
|
||||
/**
|
||||
* Areas
|
||||
*
|
||||
* @return array ['visible' => ['width', 'height'], 'blank' => ['width', 'height']]
|
||||
* @return array The product type areas in centimeters (cm) ['visible' => ['width', 'height'], 'blank' => ['width', 'height']]
|
||||
*/
|
||||
public function areas(): array
|
||||
{
|
||||
return match ($this) {
|
||||
type::pin_37 => [
|
||||
'visible' => [
|
||||
'width' => 37,
|
||||
'height' => 37
|
||||
'width' => 3.7,
|
||||
'height' => 3.7
|
||||
],
|
||||
'blank' => [
|
||||
'width' => 48.5,
|
||||
'height' => 48.5
|
||||
'width' => 4.85,
|
||||
'height' => 4.85
|
||||
]
|
||||
]
|
||||
};
|
||||
@@ -6,7 +6,9 @@ namespace svoboda\pechatalka\models;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\core,
|
||||
svoboda\pechatalka\models\enumerations\products\type as product_type;
|
||||
/* svoboda\pechatalka\models\enumerations\paper\type as paper_type, */
|
||||
svoboda\pechatalka\models\enumerations\paper\format as paper_format,
|
||||
svoboda\pechatalka\models\enumerations\product\type as product_type;
|
||||
|
||||
// Svoboda time
|
||||
use svoboda\time\statement as svoboda;
|
||||
@@ -23,6 +25,7 @@ use Zanzara\Telegram\Type\User as telegram;
|
||||
|
||||
// Built-in libraries
|
||||
use Imagick as imagick,
|
||||
ImagickKernel as imagick_kernel,
|
||||
ImagickPixel as imagick_pixel,
|
||||
ImagickDraw as imagick_draw,
|
||||
Exception as exception,
|
||||
@@ -39,120 +42,168 @@ use Imagick as imagick,
|
||||
final class paper extends core
|
||||
{
|
||||
/**
|
||||
* A5
|
||||
*
|
||||
*
|
||||
* Generate
|
||||
*
|
||||
* @param paper_format $format
|
||||
* @param product_type $type
|
||||
* @param array $products
|
||||
* @param array $canvas
|
||||
* @param int|float $dpi Dots (pixels) per Inch (used with centimeters)
|
||||
* @param bool $fit Fit the maximum number of blanks on paper? (duplication)
|
||||
*
|
||||
* @return record The account record from the database
|
||||
*/
|
||||
public static function a5(product_type $type, array $products, array $canvas = []): mixed
|
||||
public static function generate(paper_format $format, product_type $type, array $products, array $canvas = [], int|float $dpi = 300, bool $fit = true): mixed
|
||||
{
|
||||
// Initializing the print DPI
|
||||
define('dpi', 80);
|
||||
/* define('dpi', 300); */
|
||||
// Initializing the paper dimensions
|
||||
$dimensions = $format->dimensions();
|
||||
$width = (int) round($dimensions['width'] * $dpi);
|
||||
$height = (int) round($dimensions['height'] * $dpi);
|
||||
unset($dimensions);
|
||||
|
||||
// Initializing the A5 paper dimensions
|
||||
$a5 = [
|
||||
'width' => (int) round(10.5 * dpi),
|
||||
'height' => (int) round(14.8 * dpi)
|
||||
// Initializing the product areas
|
||||
$areas = $type->areas();
|
||||
|
||||
// Calculating the product blank dimensions by the print $dpi
|
||||
$blank = [
|
||||
'width' => (int) round($areas['blank']['width'] * $dpi),
|
||||
'height' => (int) round($areas['blank']['height'] * $dpi)
|
||||
];
|
||||
|
||||
// Initializing the paper
|
||||
$paper = new imagick();
|
||||
$paper->setResolution(dpi, dpi);
|
||||
$paper->newImage($a5['width'], $a5['height'], new imagick_pixel("white"));
|
||||
$paper->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER);
|
||||
$paper->setImageFormat("jpg");
|
||||
// Calculating the $dpi ratio of the pechatalka interface to the blank dimensions
|
||||
$ratio = [
|
||||
'width' => $blank['width'] / $canvas['width'],
|
||||
'height' => $blank['height'] / $canvas['height']
|
||||
];
|
||||
|
||||
foreach ($products as $product) {
|
||||
// Iterating over products
|
||||
// Initializing the circle mask
|
||||
$mask = new imagick();
|
||||
$mask->setResolution($dpi, $dpi);
|
||||
$mask->newImage($blank['width'], $blank['height'], '#0000');
|
||||
$mask->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER);
|
||||
$mask->setimageformat('png');
|
||||
$mask->setimagematte(true);
|
||||
$draw = new imagick_draw();
|
||||
$draw->setfillcolor('#fff');
|
||||
$draw->circle($blank['width'] / 2, $blank['height'] / 2, $blank['width'] / 2, $blank['height']);
|
||||
$mask->drawimage($draw);
|
||||
|
||||
foreach ($product as $layer) {
|
||||
// Iterating over the product layers
|
||||
// Initializing the paper places
|
||||
$places = $format->places(type: $type);
|
||||
|
||||
// Filtering
|
||||
empty($layer['scale']) || $layer['scale'] == 0 and $layer['scale'] = 1;
|
||||
// Calculating the amount of products
|
||||
$have = count($products);
|
||||
|
||||
// Initializing the product areas
|
||||
$areas = $type->areas();
|
||||
// Calculating the amount of places per paper
|
||||
$limit = count($places);
|
||||
|
||||
// Calculating the product blank dimensions by the print DPI
|
||||
$blank = [
|
||||
'width' => (int) round($areas['blank']['width'] / 10 * dpi),
|
||||
'height' => (int) round($areas['blank']['height'] / 10 * dpi)
|
||||
];
|
||||
// Calculating the amount of missing products on the paper
|
||||
$need = $limit - $have;
|
||||
|
||||
// Calculating the DPI ratio of the pechatalka interface to the blank dimensions
|
||||
$ratio = [
|
||||
'width' => $blank['width'] / $canvas['width'],
|
||||
'height' => $blank['height'] / $canvas['height']
|
||||
];
|
||||
if ($fit && $have < $limit) {
|
||||
// Received less products then can be fit on the page
|
||||
|
||||
// Initializing the circle mask
|
||||
$circle = new imagick();
|
||||
$circle->setResolution(dpi, dpi);
|
||||
$circle->newImage($blank['width'], $blank['height'], '#0008');
|
||||
$circle->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER);
|
||||
$circle->setimageformat('png');
|
||||
$circle->setimagematte(true);
|
||||
$draw = new imagick_draw();
|
||||
$draw->setfillcolor('#fff');
|
||||
$draw->circle($blank['width'] / 2, $blank['height'] / 2, $blank['width'] / 2, $blank['height']);
|
||||
$circle->drawimage($draw);
|
||||
for (; $need++ < $limit;) {
|
||||
// Iterating over free places
|
||||
|
||||
// Initializing the layer image
|
||||
$image = new imagick();
|
||||
$image->setResolution(dpi, dpi);
|
||||
$image->readImage($layer['image']);
|
||||
$image->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER);
|
||||
$image->setimagematte(true);
|
||||
|
||||
$width = (int) round($blank['width'] * $layer['scale']);
|
||||
$image->adaptiveResizeImage($width, 0);
|
||||
/* $image->roundCornersImage(50, 50); */
|
||||
|
||||
$offset = [
|
||||
'x' => ($blank['width'] - $image->getImageWidth()) / 2,
|
||||
'y' => ($blank['height'] - $image->getImageHeight()) / 2
|
||||
];
|
||||
|
||||
$vertical = $blank['height'] - $image->getImageHeight();
|
||||
|
||||
|
||||
|
||||
// Добавить нормальные комментарии после глубокго тестирования
|
||||
|
||||
|
||||
|
||||
|
||||
// Reinitializing the product layer offsets
|
||||
$layer['x'] = (int) round($layer['x'] * $ratio['width']);
|
||||
$layer['y'] = (int) round($layer['y'] * $ratio['height']);
|
||||
|
||||
$image->compositeImage(
|
||||
$circle,
|
||||
imagick::COMPOSITE_DSTIN,
|
||||
(int) round(-$layer['x'] - $offset['x']),
|
||||
/* (int) round(-$layer['y'] - $offset['y'] - $vertical / 2) */
|
||||
(int) round(-$layer['y'] - $offset['y'])
|
||||
);
|
||||
|
||||
// Compositing the layer with the paper
|
||||
$paper->setImageVirtualPixelMethod(imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
|
||||
$paper->setImageArtifact('compose:args', "1,0,-0.5,0.5");
|
||||
$paper->compositeImage(
|
||||
$image,
|
||||
imagick::COMPOSITE_MATHEMATICS,
|
||||
(int) round($a5['width'] / 2 - $blank['width'] / 2 + $layer['x'] + $offset['x']),
|
||||
/* (int) round($a5['height'] / 2 - $blank['height'] / 2 + $layer['y'] + $offset['y'] + $vertical / 2) */
|
||||
(int) round($a5['height'] / 2 - $blank['height'] / 2 + $layer['y'] + $offset['y'])
|
||||
);
|
||||
|
||||
// Writing the paper file
|
||||
$paper->writeImage(INDEX . DIRECTORY_SEPARATOR . 'test.jpg');
|
||||
// Dublicating the product
|
||||
$products[] = $products[rand(0, $have - 1)];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
// Calculating the amount of papers
|
||||
$amount = $have % $limit;
|
||||
|
||||
for ($page = 0; $page < $amount; $page++) {
|
||||
// Iterating over pages
|
||||
|
||||
// Initializing the paper
|
||||
$paper = new imagick();
|
||||
$paper->setResolution($dpi, $dpi);
|
||||
$paper->newImage($width, $height, new imagick_pixel("#fff"));
|
||||
$paper->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER);
|
||||
$paper->setImageFormat("jpg");
|
||||
$paper->setimagematte(true);
|
||||
|
||||
// Calculating the products pages offset
|
||||
$offset = $page === 0 ? 0 : $page * $amount;
|
||||
|
||||
foreach ($places as $index => $place) {
|
||||
// Iterating over places
|
||||
|
||||
// Recalculating the place coordinates with DPI
|
||||
$place['x'] *= $dpi;
|
||||
$place['y'] *= $dpi;
|
||||
|
||||
// Initializing the product
|
||||
$product = $products[$offset + $index];
|
||||
|
||||
foreach ($product as $layer) {
|
||||
// Iterating over the product layers
|
||||
|
||||
// Filtering and normalizing the layer parameters
|
||||
empty($layer['scale']) || $layer['scale'] == 0 and $layer['scale'] = 1;
|
||||
|
||||
// Initializing the layer image
|
||||
$image = new imagick();
|
||||
$image->setResolution($dpi, $dpi);
|
||||
$image->readImage($layer['image']);
|
||||
$image->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER);
|
||||
$image->setimagematte(true);
|
||||
|
||||
// Resizing the layer image
|
||||
$image->adaptiveResizeImage((int) round($blank['width'] * $layer['scale']), 0);
|
||||
|
||||
if (!empty($layer['corners'])) {
|
||||
// Received the layer image corners
|
||||
|
||||
// Masking the layer image with corners
|
||||
$image->roundCornersImage($layer['corners'], $layer['corners']);
|
||||
}
|
||||
|
||||
// Calculating the layer image coordinates by the layer image mask
|
||||
$layer['x'] = (int) round(($layer['x'] - ($canvas['width'] - $layer['width']) / 2) * $ratio['width'] + ($blank['width'] - $image->getImageWidth()) / 2);
|
||||
$layer['y'] = (int) round(($layer['y'] - ($canvas['height'] - $layer['height']) / 2) * $ratio['height'] + ($blank['height'] - $image->getImageHeight()) / 2);
|
||||
|
||||
// Compositing the layer image mask with the layer image
|
||||
$image->compositeImage(
|
||||
$mask,
|
||||
imagick::COMPOSITE_DSTIN,
|
||||
(int) round(-$layer['x']),
|
||||
(int) round(-$layer['y'])
|
||||
);
|
||||
|
||||
// Drawing the cutting line
|
||||
$draw = new imagick_draw();
|
||||
$draw->setfillcolor($canvas['background'] ?? '#fff');
|
||||
$stroke = 2;
|
||||
$draw->setStrokeOpacity(1);
|
||||
$draw->setStrokeColor('#000');
|
||||
$draw->setStrokeWidth($stroke);
|
||||
$draw->circle(
|
||||
$place['x'] + $blank['width'] / 2,
|
||||
$place['y'] + $blank['height'] / 2,
|
||||
round($place['x'] + $blank['width'] / 2 + $stroke),
|
||||
round($place['y'] + $blank['height'] + $stroke)
|
||||
);
|
||||
$paper->drawimage($draw);
|
||||
|
||||
// Compositing the layer image with the paper
|
||||
$paper->compositeImage(
|
||||
$image,
|
||||
$image->getImageCompose(),
|
||||
(int) round($place['x'] + $layer['x']),
|
||||
(int) round($place['y'] + $layer['y'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Writing the paper file
|
||||
$paper->writeImage(INDEX . DIRECTORY_SEPARATOR . 'test.jpg');
|
||||
}
|
||||
|
||||
|
||||
// Exit (success)
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace svoboda\pechatalka\models;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\core,
|
||||
svoboda\pechatalka\models\enumerations\products\type as product_type;
|
||||
svoboda\pechatalka\models\enumerations\product\type as product_type;
|
||||
|
||||
// Svoboda time
|
||||
use svoboda\time\statement as svoboda;
|
||||
|
||||
@@ -148,15 +148,20 @@ Object.assign(
|
||||
if (typeof index === "number") {
|
||||
// Initialized the layer index
|
||||
|
||||
// Initializing the layer
|
||||
product[index] ??= {};
|
||||
// Calculating the difference between the canvas and the layer
|
||||
const difference = {
|
||||
width: canvas.offsetWidth - layer.offsetWidth,
|
||||
height: canvas.offsetHeight - layer.offsetHeight
|
||||
};
|
||||
|
||||
// Writing the layer parameters
|
||||
product[index].x =
|
||||
parseInt(layer.style.getPropertyValue("left")) || 0;
|
||||
product[index].y =
|
||||
parseInt(layer.style.getPropertyValue("top")) || 0;
|
||||
product[index].scale = parseFloat(layer.style.getPropertyValue("scale") || 1);
|
||||
// Initializing the layer
|
||||
product[index] = {
|
||||
x: parseInt(layer.style.getPropertyValue("left")) || (difference.width > 0 ? difference.width / 2 : 0),
|
||||
y: parseInt(layer.style.getPropertyValue("top")) || (difference.height > 0 ? difference.height / 2 : 0),
|
||||
width: parseInt(layer.offsetWidth),
|
||||
height: parseInt(layer.offsetHeight),
|
||||
scale: parseFloat(layer.style.getPropertyValue("scale") || 1)
|
||||
};
|
||||
|
||||
// Initializing the layer type
|
||||
const type = layer.getAttribute("data-layer-type");
|
||||
|
||||
@@ -13,6 +13,12 @@ core.modules.connect(["generator", "pechatalka"])
|
||||
]),
|
||||
);
|
||||
|
||||
// Activating the keyboard function
|
||||
instance.keyboard();
|
||||
|
||||
// Activating the drag and drop function
|
||||
instance.dragdrop();
|
||||
|
||||
// instence.layers.set('interface', true)
|
||||
|
||||
// Reinitializing the `layer create` event
|
||||
|
||||
@@ -93,14 +93,31 @@ div#pechatalka {
|
||||
position: relative;
|
||||
width: var(--diameter-cut, 300px);
|
||||
height: var(--diameter-cut, 300px);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: clip;
|
||||
border-radius: 100%;
|
||||
border: 2px solid var(--background-color-inverted);
|
||||
outline: 2px solid var(--background-color-inverted);
|
||||
background-color: var(--paper, var(--white, #fff));
|
||||
|
||||
&:is(.drag) {
|
||||
&:before {
|
||||
opacity: 1;
|
||||
background: radial-gradient(1px,
|
||||
transparent calc(var(--diameter-display, 77.08%) / 2),
|
||||
#53decbab);
|
||||
transition: opacity 0s, background 0s;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.drag) {
|
||||
&:before {
|
||||
transition: opacity 0.1s ease-out, background 0.1s ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
&:before {
|
||||
z-index: 500;
|
||||
position: absolute;
|
||||
@@ -112,7 +129,6 @@ div#pechatalka {
|
||||
background: radial-gradient(1px,
|
||||
transparent calc(var(--diameter-display, 77.08%) / 2),
|
||||
#000a);
|
||||
transition: opacity 0.1s ease-out;
|
||||
}
|
||||
|
||||
&:has(div.layer) {
|
||||
@@ -153,9 +169,10 @@ div#pechatalka {
|
||||
/* min-width: 50%;
|
||||
max-width: 200%; */
|
||||
width: calc(var(--diameter-cut, var(--width, 100%)) + var(--width-zoom, 0px));
|
||||
height: calc(var(--diameter-cut, var(--width, 100%)) + var(--width-zoom, 0px));
|
||||
/* height: calc(var(--diameter-cut, var(--width, 100%)) + var(--width-zoom, 0px)); */
|
||||
cursor: grab;
|
||||
align-content: center;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
|
||||
&:active {
|
||||
cursor: grabbing;
|
||||
@@ -170,28 +187,29 @@ div#pechatalka {
|
||||
}
|
||||
|
||||
>button {
|
||||
&:is(:disabled, [disabled="true"], .disabled) {
|
||||
display: none !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
&:is(.delete) {
|
||||
--offset: 5px;
|
||||
--size: 40px;
|
||||
z-index: 1500;
|
||||
position: fixed;
|
||||
margin-top: var(--offset);
|
||||
margin-left: calc((var(--size, 40px) + var(--offset)) * -1);
|
||||
position: absolute;
|
||||
top: calc(var(--vertical-difference, 0px) / 2 + var(--offset, 5px));
|
||||
right: calc(var(--image-right, 0px) + var(--offset, 5px));
|
||||
width: var(--size, 40px);
|
||||
height: var(--size, 40px);
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
mix-blend-mode: overlay;
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
border: unset;
|
||||
background: unset;
|
||||
transition: pointer-events 0s, opacity 0.1s ease-in;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
&:is(:disabled, [disabled="true"], .disabled) {
|
||||
opacity: 0;
|
||||
pointer-events: none !important;
|
||||
transition: pointer-events 0s linear 0.1s, opacity 0.1s ease-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% block js %}
|
||||
<script src="https://telegram.org/js/telegram-web-app.js"></script>
|
||||
<!-- <script src="https://telegram.org/js/telegram-web-app.js"></script> -->
|
||||
<script src="/js/modules/damper.mjs" type="module"></script>
|
||||
<script src="/js/core.js"></script>
|
||||
<script src="/js/modules/telegram.mjs" type="module"></script>
|
||||
|
||||
Reference in New Issue
Block a user