mod: ядро (12) вместо синусоид-червячков -- снежинки
This commit is contained in:
@@ -15,6 +15,7 @@ class HalftoneGenerateForm(forms.Form):
|
||||
("star", "Звезда"),
|
||||
("cross", "Крестик"),
|
||||
("line", "Линия"),
|
||||
("snowflake", "Снежинка"),
|
||||
("wave", "Волна"),
|
||||
("heart", "Сердечко"),
|
||||
]
|
||||
|
||||
@@ -76,9 +76,17 @@ def generate_shape_def(shape: str, radius: int, shape_id: str) -> str:
|
||||
th = max(1, round(r * 0.25))
|
||||
return f'<rect id="{shape_id}" x="{-r}" y="{-th}" width="{2*r}" height="{2*th}" rx="1"/>'
|
||||
|
||||
case "wave":
|
||||
th = max(1.0, r * 0.3)
|
||||
return f'<path id="{shape_id}" d="M{-r},0 Q{-r/2:.1f},{-r} 0,0 T{r},0" fill="none" stroke="currentColor" stroke-width="{th:.1f}"/>'
|
||||
case "snowflake":
|
||||
points = []
|
||||
inner_r = max(0.5, r * 0.25)
|
||||
for i in range(16):
|
||||
angle = i * math.pi / 8 - math.pi / 2
|
||||
curr_r = r if i % 2 == 0 else inner_r
|
||||
px = round(curr_r * math.cos(angle), 1)
|
||||
py = round(curr_r * math.sin(angle), 1)
|
||||
points.append(f"{px},{py}")
|
||||
pts_str = " ".join(points)
|
||||
return f'<polygon id="{shape_id}" points="{pts_str}"/>'
|
||||
|
||||
case "heart":
|
||||
r_top = round(r * 0.3)
|
||||
@@ -114,7 +122,7 @@ def generate_halftone_svg(
|
||||
- image: PIL Image, файловый объект (BytesIO), байты или путь к файлу
|
||||
- cols: число точек по наибольшей стороне сетки (10-200)
|
||||
- max_radius: максимальный радиус/размер точки (3-20)
|
||||
- shape: тип фигуры ('circle', 'ring', 'square', 'diamond', 'triangle', 'hexagon', 'star', 'cross', 'line', 'wave', 'heart')
|
||||
- shape: тип фигуры ('circle', 'ring', 'square', 'diamond', 'triangle', 'hexagon', 'star', 'cross', 'line', 'snowflake', 'heart')
|
||||
- color: основной HEX цвет (например '#a855ff')
|
||||
- opacity: коэффициент непрозрачности (0.0 - 1.0)
|
||||
- blink: интенсивность мерцания (0 - выключено/статичный, 1-10 - скорость)
|
||||
|
||||
@@ -78,7 +78,7 @@ class HalftoneServiceTests(BaseMediaTestCase):
|
||||
self.assertIn("<desc>Generated by Hypn0", svg)
|
||||
|
||||
def test_generate_shapes(self):
|
||||
shapes = ["circle", "ring", "square", "diamond", "triangle", "hexagon", "star", "cross", "line", "wave", "heart"]
|
||||
shapes = ["circle", "ring", "square", "diamond", "triangle", "hexagon", "star", "cross", "line", "snowflake", "heart"]
|
||||
for shape in shapes:
|
||||
svg = generate_halftone_svg(self.img, cols=20, max_radius=5, shape=shape)
|
||||
self.assertIn("<svg", svg)
|
||||
@@ -95,6 +95,11 @@ class HalftoneServiceTests(BaseMediaTestCase):
|
||||
self.assertIn('<path id="s', heart_svg)
|
||||
self.assertNotIn('transform="scale', heart_svg)
|
||||
|
||||
# Проверяем структуру снежинки: 8-лучевой полигон с точками
|
||||
snowflake_svg = generate_halftone_svg(self.img, cols=20, max_radius=8, shape="snowflake")
|
||||
self.assertIn('<polygon id="s', snowflake_svg)
|
||||
self.assertIn('points="', snowflake_svg)
|
||||
|
||||
def test_generate_static_blink_zero(self):
|
||||
svg = generate_halftone_svg(self.img, cols=20, blink=0)
|
||||
self.assertIn("animation:none", svg)
|
||||
|
||||
@@ -250,12 +250,12 @@
|
||||
</label>
|
||||
|
||||
|
||||
<!-- 11. Волна / Синусоида -->
|
||||
<label class="cursor-pointer group" title="Волна">
|
||||
<input type="radio" name="shape" value="wave" class="hidden peer">
|
||||
<!-- 11. Снежинка / Звездочка -->
|
||||
<label class="cursor-pointer group" title="Снежинка">
|
||||
<input type="radio" name="shape" value="snowflake" class="hidden peer">
|
||||
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
|
||||
<svg class="w-6 h-6 stroke-current transition-colors" fill="none" stroke-width="2.5" stroke-linecap="round" viewBox="0 0 24 24">
|
||||
<path d="M2 12c2.5-4 5.5-4 8 0s5.5 4 8 0 3.5-4 4-4"/>
|
||||
<svg class="w-6 h-6 fill-current transition-colors" viewBox="0 0 24 24">
|
||||
<polygon points="12,2 13.2,9.5 19.1,4.9 14.5,10.8 22,12 14.5,13.2 19.1,19.1 13.2,14.5 12,22 10.8,14.5 4.9,19.1 9.5,13.2 2,12 9.5,10.8 4.9,4.9 10.8,9.5"/>
|
||||
</svg>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
Reference in New Issue
Block a user