From 3ab4d76e63a911561ae3affa33fb1a4aedb0d9c0 Mon Sep 17 00:00:00 2001 From: Dauren777 Date: Tue, 7 Jul 2026 13:33:06 +0000 Subject: [PATCH] =?UTF-8?q?v2=20=E2=80=94=20real=20PowerPoint=20animations?= =?UTF-8?q?=20(fly-in,=20zoom,=20spin,=20bounce)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- create_pptx.py | 684 ++++++++++++++++++++++--------------- Казахстан_Презентация.pptx | Bin 42543 -> 47323 bytes 2 files changed, 401 insertions(+), 283 deletions(-) diff --git a/create_pptx.py b/create_pptx.py index cb30602..abdbac2 100644 --- a/create_pptx.py +++ b/create_pptx.py @@ -1,343 +1,461 @@ #!/usr/bin/env python3 -"""Презентация о Казахстане — чистый PPTX без кривых XML-анимаций.""" +""" +Презентация о Казахстане с настоящими PowerPoint-анимациями. +Подход: создаём PPTX через python-pptx, затем распаковываем, +вставляем правильный XML и запаковываем обратно. +""" from pptx import Presentation from pptx.util import Inches, Pt, Emu from pptx.dml.color import RGBColor -from pptx.enum.text import PP_ALIGN, MSO_ANCHOR +from pptx.enum.text import PP_ALIGN from pptx.enum.shapes import MSO_SHAPE from pptx.oxml.ns import qn -import lxml.etree as etree +import zipfile, shutil, os, copy, tempfile +from lxml import etree # ── Colors ── -INK = RGBColor(0x0F, 0x12, 0x18) +INK = RGBColor(0x0F, 0x12, 0x18) CYAN = RGBColor(0x00, 0xE5, 0xFF) GOLD = RGBColor(0xE8, 0xB7, 0x30) WHITE = RGBColor(0xFF, 0xFF, 0xFF) -GRAY = RGBColor(0x5B, 0x65, 0x73) -BG_DARK = RGBColor(0x14, 0x1C, 0x28) +GRAY = RGBColor(0x5B, 0x65, 0x73) +BG = RGBColor(0x14, 0x1C, 0x28) prs = Presentation() -prs.slide_width = Inches(13.333) +prs.slide_width = Inches(13.333) prs.slide_height = Inches(7.5) W = prs.slide_width H = prs.slide_height +BL = prs.slide_layouts[6] -BLANK_LAYOUT = prs.slide_layouts[6] +# ── helpers ── +def bg(s, c): + s.background.fill.solid() + s.background.fill.fore_color.rgb = c +def txt(s, t, l, tp, w, h, sz=24, b=False, c=INK, a=PP_ALIGN.LEFT, fn='Calibri'): + tb = s.shapes.add_textbox(l, tp, w, h) + tf = tb.text_frame; tf.word_wrap = True + p = tf.paragraphs[0]; p.text = t + p.font.size = Pt(sz); p.font.bold = b; p.font.color.rgb = c; p.font.name = fn + p.alignment = a + return tb -def set_slide_transition(slide, transition_type='push', speed='med', advance_ms=None): - """Set slide transition effect.""" - timing = slide._element.find(qn('p:transition')) - if timing is None: - timing = etree.SubElement(slide._element, qn('p:transition')) +def box(s, l, tp, w, h, fc=BG, bc=None): + sh = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, l, tp, w, h) + sh.fill.solid(); sh.fill.fore_color.rgb = fc + if bc: sh.line.color.rgb = bc; sh.line.width = Pt(2) + else: sh.line.fill.background() + return sh - transitions = { - 'push': ('push', {'advClick': '1'}), - 'fade': ('fade', {'advClick': '1'}), - 'wipe': ('wipe', {'dir': 'd', 'advClick': '1'}), - 'cover': ('cover', {'dir': 'l', 'advClick': '1'}), - 'cut': ('cut', {'advClick': '1'}), - 'dissolve': ('dissolve', {'advClick': '1'}), - 'zoom': ('zoom', {'advClick': '1'}), - } - tag_name, attrs = transitions.get(transition_type, transitions['push']) - el = etree.SubElement(timing, qn(f'p:{tag_name}')) - for k, v in attrs.items(): - el.set(k, v) - if advance_ms: - timing.set('advTm', str(advance_ms)) +def circ(s, l, tp, sz, c): + sh = s.shapes.add_shape(MSO_SHAPE.OVAL, l, tp, sz, sz) + sh.fill.solid(); sh.fill.fore_color.rgb = c; sh.line.fill.background() + return sh +def rect(s, l, tp, w, h, c): + sh = s.shapes.add_shape(MSO_SHAPE.RECTANGLE, l, tp, w, h) + sh.fill.solid(); sh.fill.fore_color.rgb = c; sh.line.fill.background() + return sh -def add_bg(slide, color): - bg = slide.background - fill = bg.fill - fill.solid() - fill.fore_color.rgb = color +# counter for unique shape IDs +_shape_id = [100] +def sid(): + _shape_id[0] += 1 + return _shape_id[0] +# track shapes with their IDs for animation +anim_shapes = [] # list of (slide_idx, shape_id, animation_type, delay_ms, dur_ms) -def add_text(slide, text, left, top, width, height, - font_size=24, bold=False, color=INK, align=PP_ALIGN.LEFT, - font_name='Calibri'): - txBox = slide.shapes.add_textbox(left, top, width, height) - tf = txBox.text_frame - tf.word_wrap = True - p = tf.paragraphs[0] - p.text = text - p.font.size = Pt(font_size) - p.font.bold = bold - p.font.color.rgb = color - p.font.name = font_name - p.alignment = align - return txBox - - -def add_box(slide, left, top, width, height, fill_color=BG_DARK, - border_color=None): - shape = slide.shapes.add_shape( - MSO_SHAPE.ROUNDED_RECTANGLE, left, top, width, height - ) - shape.fill.solid() - shape.fill.fore_color.rgb = fill_color - if border_color: - shape.line.color.rgb = border_color - shape.line.width = Pt(2) - else: - shape.line.fill.background() - return shape - - -def add_circle(slide, left, top, size, color): - c = slide.shapes.add_shape(MSO_SHAPE.OVAL, left, top, size, size) - c.fill.solid() - c.fill.fore_color.rgb = color - c.line.fill.background() - return c - - -def add_rect(slide, left, top, width, height, color): - r = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height) - r.fill.solid() - r.fill.fore_color.rgb = color - r.line.fill.background() - return r - +def add_shape_with_anim(slide, slide_idx, shape, anim_type, delay_ms=0, dur_ms=500): + """Register a shape for animation. Returns the shape's spId.""" + sp = shape.shape_id + anim_shapes.append((slide_idx, sp, anim_type, delay_ms, dur_ms)) + return sp # ══════════════════════════════════════════════════════════════ # SLIDE 1 — Title # ══════════════════════════════════════════════════════════════ -s = prs.slides.add_slide(BLANK_LAYOUT) -add_bg(s, BG_DARK) -set_slide_transition(s, 'zoom') - -add_circle(s, Inches(9.5), Inches(0.8), Inches(4.5), RGBColor(0x00, 0x3D, 0x5C)) -add_circle(s, Inches(10.2), Inches(1.5), Inches(3), CYAN) -add_circle(s, Inches(-0.5), Inches(5.5), Inches(3), RGBColor(0x00, 0x3D, 0x5C)) -add_circle(s, Inches(0), Inches(6), Inches(2), GOLD) - -add_text(s, '🇰🇿', Inches(1), Inches(1.2), Inches(2), Inches(1.5), font_size=80, color=WHITE) -add_text(s, 'КАЗАХСТАН', Inches(1), Inches(2.8), Inches(8), Inches(1.5), - font_size=72, bold=True, color=WHITE) -add_text(s, 'Сердце Евразии — девятая по территории страна мира', - Inches(1), Inches(4.3), Inches(8), Inches(0.8), - font_size=24, color=GRAY) - -stats = [('2.7 млн км²', 'Площадь'), ('20 млн', 'Население'), - ('130+', 'Народов'), ('1 космодром', 'Байконур')] -for i, (val, lbl) in enumerate(stats): - x = Inches(1 + i * 3) - y = Inches(5.6) - add_box(s, x, y, Inches(2.7), Inches(1.2), RGBColor(0x1C, 0x26, 0x36)) - add_text(s, val, x + Inches(0.2), y + Inches(0.1), Inches(2.3), Inches(0.6), - font_size=24, bold=True, color=CYAN) - add_text(s, lbl, x + Inches(0.2), y + Inches(0.65), Inches(2.3), Inches(0.4), - font_size=13, color=GRAY) - +s = prs.slides.add_slide(BL); bg(s, BG) +add_shape_with_anim(s, 0, circ(s, Inches(10), Inches(0.5), Inches(3), RGBColor(0,61,92)), 'spin', 300, 2000) +add_shape_with_anim(s, 0, circ(s, Inches(10.5), Inches(1), Inches(2), CYAN), 'spin', 500, 2000) +add_shape_with_anim(s, 0, txt(s, '🇰🇿', Inches(1), Inches(1.2), Inches(2), Inches(1.5), sz=80, c=WHITE), 'zoom', 100, 800) +add_shape_with_anim(s, 0, txt(s, 'КАЗАХСТАН', Inches(1), Inches(2.8), Inches(8), Inches(1.5), sz=72, b=True, c=WHITE), 'zoom', 400, 1000) +add_shape_with_anim(s, 0, txt(s, 'Сердце Евразии — девятая по территории страна мира', Inches(1), Inches(4.3), Inches(8), Inches(0.8), sz=24, c=GRAY), 'fly', 700, 800) +for i, (v, l) in enumerate([('2.7 млн км²','Площадь'),('20 млн','Население'),('130+','Народов'),('1 космодром','Байконур')]): + x = Inches(1 + i*3); y = Inches(5.6) + b = box(s, x, y, Inches(2.7), Inches(1.2), RGBColor(28,38,54)) + txt(s, v, x+Inches(.2), y+Inches(.1), Inches(2.3), Inches(.6), sz=24, b=True, c=CYAN) + txt(s, l, x+Inches(.2), y+Inches(.65), Inches(2.3), Inches(.4), sz=13, c=GRAY) + add_shape_with_anim(s, 0, b, 'bounce', 900+i*150, 600) # ══════════════════════════════════════════════════════════════ # SLIDE 2 — Geography # ══════════════════════════════════════════════════════════════ -s = prs.slides.add_slide(BLANK_LAYOUT) -add_bg(s, WHITE) -set_slide_transition(s, 'push') - -add_rect(s, 0, 0, W, Inches(1.4), BG_DARK) -add_text(s, 'ГЕОГРАФИЯ', Inches(0.8), Inches(0.3), Inches(8), Inches(0.8), - font_size=36, bold=True, color=CYAN) -add_text(s, 'От каспийских берегов до алтайских гор', Inches(0.8), Inches(1.4), - Inches(8), Inches(0.5), font_size=16, color=GRAY) - -geo = [ - ('🏔️', 'Горы', 'Тянь-Шань, Чу-Илийские горы, Алтай.\nВысшая точка — Хан-Тенгри (7010 м)'), - ('🌊', 'Каспийское море', 'Крупнейшее озеро мира.\nПобережье тянется на 1894 км'), - ('🏜️', 'Степи', 'Бескрайние равнины —\nисторическая родина кочевников'), - ('🌾', 'Озёра', 'Балхаш, Алаколь, Маркаколь —\nболее 45 000 озёр'), -] -for i, (em, nm, ds) in enumerate(geo): - col, row = i % 2, i // 2 - x = Inches(0.8 + col * 6.2) - y = Inches(2.2 + row * 2.5) - add_box(s, x, y, Inches(5.6), Inches(2.2), RGBColor(0xF5, 0xF7, 0xFA)) - add_text(s, em, x + Inches(0.3), y + Inches(0.15), Inches(1), Inches(0.7), - font_size=38) - add_text(s, nm, x + Inches(1.3), y + Inches(0.2), Inches(4), Inches(0.5), - font_size=22, bold=True, color=INK) - add_text(s, ds, x + Inches(1.3), y + Inches(0.75), Inches(4), Inches(1.2), - font_size=14, color=GRAY) - +s = prs.slides.add_slide(BL); bg(s, WHITE) +rect(s, 0, 0, W, Inches(1.4), BG) +add_shape_with_anim(s, 1, txt(s, 'ГЕОГРАФИЯ', Inches(.8), Inches(.3), Inches(8), Inches(.8), sz=36, b=True, c=CYAN), 'fly', 100, 600) +geo = [('🏔️','Горы','Тянь-Шань, Алтай. Хан-Тенгри 7010 м'), + ('🌊','Каспий','Крупнейшее озеро мира. 1894 км'), + ('🏜️','Степи','Родина кочевников'), + ('🌾','Озёра','45 000+ озёр по всей стране')] +for i,(em,nm,ds) in enumerate(geo): + c2,r2 = i%2, i//2 + x = Inches(.8+c2*6.2); y = Inches(2.2+r2*2.5) + b = box(s, x, y, Inches(5.6), Inches(2.2), RGBColor(245,247,250)) + txt(s, em, x+Inches(.3), y+Inches(.15), Inches(1), Inches(.7), sz=38) + txt(s, nm, x+Inches(1.3), y+Inches(.2), Inches(4), Inches(.5), sz=22, b=True, c=INK) + txt(s, ds, x+Inches(1.3), y+Inches(.75), Inches(4), Inches(1.2), sz=14, c=GRAY) + add_shape_with_anim(s, 1, b, 'fly', 300+i*200, 700) # ══════════════════════════════════════════════════════════════ # SLIDE 3 — Facts # ══════════════════════════════════════════════════════════════ -s = prs.slides.add_slide(BLANK_LAYOUT) -add_bg(s, BG_DARK) -set_slide_transition(s, 'fade') - -add_text(s, 'ЦИФРЫ И ФАКТЫ', Inches(0.8), Inches(0.6), Inches(10), Inches(1), - font_size=40, bold=True, color=WHITE) -add_text(s, 'Казахстан в цифрах', Inches(0.8), Inches(1.4), Inches(6), Inches(0.5), - font_size=18, color=GRAY) - -facts = [('9', 'по величине\nв мире'), ('1991', 'год\nнезависимости'), - ('70+', 'тонн золота\nв год'), ('1', 'космодром\nБайконур'), - ('3', 'столицы\nв истории')] -for i, (num, txt) in enumerate(facts): - x = Inches(0.5 + i * 2.5) - add_box(s, x, Inches(2.5), Inches(2.2), Inches(3.5), - RGBColor(0x1C, 0x26, 0x36), CYAN) - add_text(s, num, x + Inches(0.2), Inches(2.9), Inches(1.8), Inches(1.2), - font_size=52, bold=True, color=CYAN, align=PP_ALIGN.CENTER) - add_text(s, txt, x + Inches(0.2), Inches(4.2), Inches(1.8), Inches(1.4), - font_size=14, color=GRAY, align=PP_ALIGN.CENTER) - -add_rect(s, Inches(0.8), Inches(6.5), Inches(11.7), Inches(0.04), CYAN) - +s = prs.slides.add_slide(BL); bg(s, BG) +add_shape_with_anim(s, 2, txt(s, 'ЦИФРЫ И ФАКТЫ', Inches(.8), Inches(.6), Inches(10), Inches(1), sz=40, b=True, c=WHITE), 'zoom', 100, 600) +facts = [('9','по величине\nв мире'),('1991','год\nнезависимости'),('70+','тонн золота\nв год'),('1','космодром\nБайконур'),('3','столицы\nв истории')] +for i,(n,t) in enumerate(facts): + x = Inches(.5+i*2.5) + b = box(s, x, Inches(2.5), Inches(2.2), Inches(3.5), RGBColor(28,38,54), CYAN) + txt(s, n, x+Inches(.2), Inches(2.9), Inches(1.8), Inches(1.2), sz=52, b=True, c=CYAN, a=PP_ALIGN.CENTER) + txt(s, t, x+Inches(.2), Inches(4.2), Inches(1.8), Inches(1.4), sz=14, c=GRAY, a=PP_ALIGN.CENTER) + add_shape_with_anim(s, 2, b, 'zoom', 200+i*200, 800) # ══════════════════════════════════════════════════════════════ # SLIDE 4 — Culture # ══════════════════════════════════════════════════════════════ -s = prs.slides.add_slide(BLANK_LAYOUT) -add_bg(s, RGBColor(0xF0, 0xF4, 0xF8)) -set_slide_transition(s, 'cover') - -add_rect(s, 0, 0, W, Inches(1.4), BG_DARK) -add_text(s, 'КУЛЬТУРА И ТРАДИЦИИ', Inches(0.8), Inches(0.3), Inches(10), Inches(0.8), - font_size=36, bold=True, color=GOLD) - -culture = [ - ('🦅', 'Беркутчи', 'Соколиная охота с орлами — наследие ЮНЕСКО'), - ('🎪', 'Юрта', 'Легко разборное жилище — символ свободы'), - ('🎶', 'Домбра', 'Двухструнный инструмент — душа кюев'), - ('🤼', 'Байге', 'Конные скачки на длинные дистанции'), - ('🎭', 'Наурыз', 'Праздник весны — 7 блюд, 22 марта'), - ('📖', 'Абай', 'Великий поэт, философ, мыслитель'), -] -for i, (em, nm, ds) in enumerate(culture): - col, row = i % 3, i // 3 - x = Inches(0.8 + col * 4.1) - y = Inches(1.8 + row * 2.6) - add_box(s, x, y, Inches(3.7), Inches(2.2), WHITE) - add_text(s, em, x + Inches(0.3), y + Inches(0.15), Inches(1), Inches(0.7), - font_size=36) - add_text(s, nm, x + Inches(1.2), y + Inches(0.2), Inches(2.2), Inches(0.5), - font_size=20, bold=True, color=INK) - add_text(s, ds, x + Inches(0.3), y + Inches(1), Inches(3.2), Inches(1), - font_size=14, color=GRAY) - +s = prs.slides.add_slide(BL); bg(s, RGBColor(240,244,248)) +rect(s, 0, 0, W, Inches(1.4), BG) +add_shape_with_anim(s, 3, txt(s, 'КУЛЬТУРА', Inches(.8), Inches(.3), Inches(10), Inches(.8), sz=36, b=True, c=GOLD), 'fly', 100, 600) +cult = [('🦅','Беркутчи','Охота с орлами — ЮНЕСКО'),('🎪','Юрта','Символ свободы кочевников'), + ('🎶','Домбра','Душа казахских кюев'),('🤼','Байге','Конные скачки'), + ('🎭','Наурыз','7 блюд, 22 марта'),('📖','Абай','Поэт и мыслитель')] +for i,(em,nm,ds) in enumerate(cult): + c2,r2 = i%3, i//3 + x = Inches(.8+c2*4.1); y = Inches(1.8+r2*2.6) + b = box(s, x, y, Inches(3.7), Inches(2.2), WHITE) + txt(s, em, x+Inches(.3), y+Inches(.15), Inches(1), Inches(.7), sz=36) + txt(s, nm, x+Inches(1.2), y+Inches(.2), Inches(2.2), Inches(.5), sz=20, b=True, c=INK) + txt(s, ds, x+Inches(.3), y+Inches(1), Inches(3.2), Inches(1), sz=14, c=GRAY) + add_shape_with_anim(s, 3, b, 'fly', 250+i*180, 700) # ══════════════════════════════════════════════════════════════ # SLIDE 5 — Cities # ══════════════════════════════════════════════════════════════ -s = prs.slides.add_slide(BLANK_LAYOUT) -add_bg(s, WHITE) -set_slide_transition(s, 'push') - -add_text(s, 'ГОРОДА', Inches(0.8), Inches(0.6), Inches(10), Inches(1), - font_size=40, bold=True, color=INK) -add_text(s, 'Мегаполисы Казахстана', Inches(0.8), Inches(1.3), Inches(6), Inches(0.5), - font_size=18, color=GRAY) - -cities = [ - ('АСТАНА', 'Столица с 1997 г.\nБайтерек, Хан-Шатыр,\nфонтаны «Танкіри»', CYAN), - ('АЛМАТЫ', 'Бывшая столица\nГоры, Медеу, Шымбулак,\nалматинские яблоки', GOLD), - ('ШЫМКЕНТ', 'Третий город\nЮжные ворота,\nжаркий климат', RGBColor(0x2A, 0x9D, 0x8F)), -] -for i, (nm, ds, clr) in enumerate(cities): - x = Inches(0.8 + i * 4.1) - add_box(s, x, Inches(2.2), Inches(3.7), Inches(4.5), RGBColor(0xF5, 0xF7, 0xFA)) - add_rect(s, x, Inches(2.2), Inches(3.7), Inches(0.12), clr) - add_text(s, nm, x + Inches(0.4), Inches(2.7), Inches(3), Inches(0.6), - font_size=28, bold=True, color=INK) - add_text(s, ds, x + Inches(0.4), Inches(3.5), Inches(3), Inches(2.5), - font_size=15, color=GRAY) - +s = prs.slides.add_slide(BL); bg(s, WHITE) +add_shape_with_anim(s, 4, txt(s, 'ГОРОДА', Inches(.8), Inches(.6), Inches(10), Inches(1), sz=40, b=True, c=INK), 'zoom', 100, 600) +cities = [('АСТАНА','Столица. Байтерек,\nХан-Шатыр',CYAN),('АЛМАТЫ','Горы, Медеу,\nШымбулак',GOLD),('ШЫМКЕНТ','Южные ворота,\nдревний город',RGBColor(42,157,143))] +for i,(nm,ds,cl) in enumerate(cities): + x = Inches(.8+i*4.1) + b = box(s, x, Inches(2.2), Inches(3.7), Inches(4.5), RGBColor(245,247,250)) + rect(s, x, Inches(2.2), Inches(3.7), Inches(.12), cl) + txt(s, nm, x+Inches(.4), Inches(2.7), Inches(3), Inches(.6), sz=28, b=True, c=INK) + txt(s, ds, x+Inches(.4), Inches(3.5), Inches(3), Inches(2.5), sz=15, c=GRAY) + add_shape_with_anim(s, 4, b, 'fly', 300+i*250, 800) # ══════════════════════════════════════════════════════════════ # SLIDE 6 — Food # ══════════════════════════════════════════════════════════════ -s = prs.slides.add_slide(BLANK_LAYOUT) -add_bg(s, RGBColor(0xFD, 0xF8, 0xEF)) -set_slide_transition(s, 'wipe') - -add_text(s, 'КУХНЯ', Inches(0.8), Inches(0.6), Inches(10), Inches(1), - font_size=40, bold=True, color=INK) -add_text(s, 'Вкус степи — просто и сытно', Inches(0.8), Inches(1.3), Inches(6), Inches(0.5), - font_size=18, color=GRAY) - -foods = [ - ('🥟', 'Бешбармак', 'Главное блюдо — мясо с лапшой.\n«Пять пальцев» — едят руками'), - ('🫕', 'Кумыс', 'Ферментированное кобылье\nмолоко — тонизирующий напиток'), - ('🫓', 'Баурсаки', 'Жареные тестовые шарики\nна каждом празднике'), - ('🍵', 'Чай с молоком', 'С солью — гостям наливают\nпервым, знак уважения'), -] -for i, (em, nm, ds) in enumerate(foods): - col, row = i % 2, i // 2 - x = Inches(0.8 + col * 6.2) - y = Inches(2.2 + row * 2.4) - add_box(s, x, y, Inches(5.6), Inches(2), WHITE, GOLD) - add_text(s, em, x + Inches(0.3), y + Inches(0.15), Inches(1), Inches(0.7), - font_size=38) - add_text(s, nm, x + Inches(1.3), y + Inches(0.2), Inches(3.5), Inches(0.5), - font_size=22, bold=True, color=INK) - add_text(s, ds, x + Inches(1.3), y + Inches(0.8), Inches(3.8), Inches(1), - font_size=14, color=GRAY) - +s = prs.slides.add_slide(BL); bg(s, RGBColor(253,248,239)) +add_shape_with_anim(s, 5, txt(s, 'КУХНЯ', Inches(.8), Inches(.6), Inches(10), Inches(1), sz=40, b=True, c=INK), 'zoom', 100, 600) +foods = [('🥟','Бешбармак','Мясо с лапшой — едят руками'),('🫕','Кумыс','Кобылье молоко'), + ('🫓','Баурсаки','Тестовые шарики на празднике'),('🍵','Чай с молоком','С солью — знак уважения')] +for i,(em,nm,ds) in enumerate(foods): + c2,r2 = i%2, i//2 + x = Inches(.8+c2*6.2); y = Inches(2.2+r2*2.4) + b = box(s, x, y, Inches(5.6), Inches(2), WHITE, GOLD) + txt(s, em, x+Inches(.3), y+Inches(.15), Inches(1), Inches(.7), sz=38) + txt(s, nm, x+Inches(1.3), y+Inches(.2), Inches(3.5), Inches(.5), sz=22, b=True, c=INK) + txt(s, ds, x+Inches(1.3), y+Inches(.8), Inches(3.8), Inches(1), sz=14, c=GRAY) + add_shape_with_anim(s, 5, b, 'bounce', 200+i*200, 700) # ══════════════════════════════════════════════════════════════ # SLIDE 7 — History # ══════════════════════════════════════════════════════════════ -s = prs.slides.add_slide(BLANK_LAYOUT) -add_bg(s, WHITE) -set_slide_transition(s, 'dissolve') - -add_text(s, 'ИСТОРИЯ', Inches(0.8), Inches(0.6), Inches(10), Inches(1), - font_size=40, bold=True, color=INK) -add_text(s, 'От кочевников до космоса', Inches(0.8), Inches(1.3), Inches(6), Inches(0.5), - font_size=18, color=GRAY) - -add_rect(s, Inches(1.6), Inches(2.2), Inches(0.06), Inches(4.8), CYAN) - -timeline = [ - ('1465', 'Казахское ханство', 'Формирование народа и кочевого уклада'), - ('XVIII', 'Российская империя', 'Присоединение, оседлый образ жизни'), - ('1955', 'Байконур', 'Запуск первого космодрома в мире'), - ('1961', 'Гагарин', 'Первый полёт в космос с Байконура'), - ('1991', 'Независимость', '16 декабря — последняя республика СССР'), - ('1997', 'Новая столица', 'Перенос столицы в Акмолу (Астану)'), -] -for i, (yr, ttl, dsc) in enumerate(timeline): - y = Inches(2.2 + i * 0.8) - dot = add_circle(s, Inches(1.4), y + Inches(0.08), Inches(0.45), - CYAN if i % 2 == 0 else GOLD) - add_text(s, yr, Inches(2.2), y, Inches(1.2), Inches(0.6), - font_size=16, bold=True, color=INK) - add_text(s, f'{ttl} — {dsc}', Inches(3.5), y, Inches(9), Inches(0.6), - font_size=14, color=GRAY) - +s = prs.slides.add_slide(BL); bg(s, WHITE) +add_shape_with_anim(s, 6, txt(s, 'ИСТОРИЯ', Inches(.8), Inches(.6), Inches(10), Inches(1), sz=40, b=True, c=INK), 'zoom', 100, 600) +rect(s, Inches(1.6), Inches(2.2), Inches(.06), Inches(4.8), CYAN) +tl = [('1465','Казахское ханство'),('XVIII','Российская империя'),('1955','Байконур'), + ('1961','Гагарин в космосе'),('1991','Независимость'),('1997','Новая столица')] +for i,(yr,ttl) in enumerate(tl): + y = Inches(2.2+i*.8) + add_shape_with_anim(s, 6, circ(s, Inches(1.4), y+Inches(.08), Inches(.45), CYAN if i%2==0 else GOLD), 'bounce', 200+i*150, 500) + txt(s, yr, Inches(2.2), y, Inches(1.2), Inches(.6), sz=16, b=True, c=INK) + txt(s, ttl, Inches(3.5), y, Inches(9), Inches(.6), sz=14, c=GRAY) # ══════════════════════════════════════════════════════════════ # SLIDE 8 — Thank You # ══════════════════════════════════════════════════════════════ -s = prs.slides.add_slide(BLANK_LAYOUT) -add_bg(s, BG_DARK) -set_slide_transition(s, 'zoom') +s = prs.slides.add_slide(BL); bg(s, BG) +add_shape_with_anim(s, 7, circ(s, Inches(10), Inches(.5), Inches(3), RGBColor(0,61,92)), 'spin', 300, 2000) +add_shape_with_anim(s, 7, circ(s, Inches(10.5), Inches(1), Inches(2), CYAN), 'spin', 500, 2000) +add_shape_with_anim(s, 7, circ(s, Inches(.5), Inches(5), Inches(2.5), RGBColor(0,61,92)), 'spin', 400, 2000) +add_shape_with_anim(s, 7, circ(s, Inches(1), Inches(5.5), Inches(1.5), GOLD), 'spin', 600, 2000) +add_shape_with_anim(s, 7, txt(s, '🇰🇿', Inches(5.5), Inches(1), Inches(2.5), Inches(1.5), sz=80, c=WHITE, a=PP_ALIGN.CENTER), 'zoom', 200, 1000) +add_shape_with_anim(s, 7, txt(s, 'СПАСИБО ЗА ВНИМАНИЕ!', Inches(1), Inches(2.8), Inches(11.3), Inches(1.2), sz=48, b=True, c=WHITE, a=PP_ALIGN.CENTER), 'fly', 500, 900) -add_circle(s, Inches(10), Inches(0.5), Inches(3), RGBColor(0x00, 0x3D, 0x5C)) -add_circle(s, Inches(10.5), Inches(1), Inches(2), CYAN) -add_circle(s, Inches(0.5), Inches(5), Inches(2.5), RGBColor(0x00, 0x3D, 0x5C)) -add_circle(s, Inches(1), Inches(5.5), Inches(1.5), GOLD) - -add_text(s, '🇰🇿', Inches(5.5), Inches(1), Inches(2.5), Inches(1.5), - font_size=80, color=WHITE, align=PP_ALIGN.CENTER) -add_text(s, 'СПАСИБО ЗА ВНИМАНИЕ!', Inches(1), Inches(2.8), Inches(11.3), Inches(1.2), - font_size=48, bold=True, color=WHITE, align=PP_ALIGN.CENTER) -add_text(s, 'Казахстан — древние традиции и современные мегаполисы,\nбескрайние степи и высокие горы', - Inches(2), Inches(4.2), Inches(9.3), Inches(1.2), - font_size=18, color=GRAY, align=PP_ALIGN.CENTER) +# ── Save initial PPTX ── +tmp_pptx = '/tmp/kz_initial.pptx' +prs.save(tmp_pptx) +print(f'✅ Created {len(prs.slides)} slides, {len(anim_shapes)} animated shapes') -# ── Save ── -out = '/srv/opencode/workspaces/users/literally.ww/kazakhstan/Казахстан_Презентация.pptx' -prs.save(out) -print(f'✅ Saved: {out}') -print(f' Slides: {len(prs.slides)}') +# ══════════════════════════════════════════════════════════════ +# STEP 2: Inject proper animation XML +# ══════════════════════════════════════════════════════════════ + +WORK = '/tmp/kz_pptx_work' +if os.path.exists(WORK): + shutil.rmtree(WORK) +os.makedirs(WORK) + +# Unzip +with zipfile.ZipFile(tmp_pptx, 'r') as z: + z.extractall(WORK) + +P = 'http://schemas.openxmlformats.org/presentationml/2006/main' +A = 'http://schemas.openxmlformats.org/drawingml/2006/main' + +def make_fly_in_xml(sp_id, delay, dur): + """Fly-in from left animation.""" + return f''' + + + + + + + ''' + +def make_anim_block(sp_id, delay, dur, anim_type): + """Generate animation block for one shape.""" + if anim_type == 'fly': + return f''' + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + ''' + elif anim_type == 'zoom': + return f''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ''' + elif anim_type == 'spin': + return f''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ''' + elif anim_type == 'bounce': + return f''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ''' + return '' + +# Process each slide +for slide_idx in range(8): + slide_path = os.path.join(WORK, 'ppt', 'slides', f'slide{slide_idx+1}.xml') + tree = etree.parse(slide_path) + root = tree.getroot() + + # Get shapes on this slide + shapes_on_slide = [(sp_id, anim, delay, dur) + for (si, sp_id, anim, delay, dur) in anim_shapes + if si == slide_idx] + + if not shapes_on_slide: + continue + + # Build timing XML + timing_parts = [] + timing_parts.append(make_fly_in_xml(0, 0, 0)) # header + + for sp_id, anim, delay, dur in shapes_on_slide: + timing_parts.append(make_anim_block(sp_id, delay, dur, anim)) + + timing_parts.append(''' + + + + + + + + + +''') + + timing_xml = ''.join(timing_parts) + timing_el = etree.fromstring(timing_xml) + root.append(timing_el) + + tree.write(slide_path, xml_declaration=True, encoding='UTF-8', standalone=True) + print(f' ✓ Slide {slide_idx+1}: {len(shapes_on_slide)} animations injected') + + +# ══════════════════════════════════════════════════════════════ +# STEP 3: Repackage +# ══════════════════════════════════════════════════════════════ +out_pptx = '/srv/opencode/workspaces/users/literally.ww/kazakhstan/Казахстан_Презентация.pptx' +with zipfile.ZipFile(out_pptx, 'w', zipfile.ZIP_DEFLATED) as zout: + for dirpath, dirnames, filenames in os.walk(WORK): + for fn in filenames: + full = os.path.join(dirpath, fn) + arc = os.path.relpath(full, WORK) + zout.write(full, arc) + +print(f'\n🎉 Saved: {out_pptx}') +print(f' {len(anim_shapes)} shape animations across 8 slides') +print(f' Animation types: fly-in, zoom, spin, bounce') +print(f' Open in PowerPoint → F5 → animations play on click/advance') diff --git a/Казахстан_Презентация.pptx b/Казахстан_Презентация.pptx index 1bd222f596a7b453c805ad3f4099cb20c1cce6de..be56ab9b7d9bdc7977452f22054a3de20ab01108 100644 GIT binary patch delta 18733 zcmZ7dV|1lW7q*SYR>$txPCB-2+vbY7Vs&iW9ox2Tb&M5utls_H@7`m7@Au;xHEPbP zYu3N>97oNnn}*oBgFsT2gM`8a0|SEtBeHKmLV|!GvTwqNpa%cn*px5}jqv|ZH(f#z z{FfJlEc-8?jWqt>2nU<|zj$&x=JNlx(IC3~7q&oAfk7d%Kh@vGFl42J1q1sgknCcO z4gA66G0_fB7paAVWf^gn~?P2#Jsg zRao);uEW}&10crc z`rbpu;((#XPTXJhn$|Mps6?OKb>-#&JazHV{#>vH%e(a+p-j9=EnYRAkL$TToUhslSw)G&h1lqpnNXV3kf_&NHi~$)vxlIodDyyib@vE* z5Pd9}CuzZOW5H`mPY|g_0NaV4(hQCW7Mp?`2mpwxYM2Sws_tOdv{_A97_R}?=d=V( zslNCP$Ne|-ZTdn5hhW{k7PQP(%vJ)Haw;bdFu|Ku!Tw!%!e1?Tsh4~X7?h&wVr*`u3TB|9OSDu(8QN9-*uksrFgqS1=AS(Wd;QYtyR8m>0^%-6iA55%emW7KNUp3rOVMq?^L(=BGyeIW1z=(F+0y`q3Jm?jt*9_H~p|VwisENIiOSC@v#%@F)Chh4W8(! z^uqCz<*3hbYwDg*SJe@R6tNT@BHfr~gDQvID^YW)r&ZmHUB!^l-S=15FTmHNF0M&v z2bAOy@+KQWv(U@l2YItTH3E>_=f?|hINs{P+UZcw-swf^E3QxL#Yi==Z$_N9=C8WJ zrO^*VW5WTaxjz>efYvKtWG>;^^}({ zSmC*uKy7daep!3NRz#N~j-*Bsp~M>skqsFE5`p_w6}krxu`eG?xsX+R3VNJ*gdqbI ztOq%@(T1s#>>+|R)@}*oi1w<$jwroa#N7S5iSY6_1*Q`sRVukyaKIea1Oto4HC8P5 zdB|_iOV%y-`38fP!^B2NiQ@>MJGNjXM#bcx0G)Nk#02aDv-TW6&sAWjV^DGyV)MMj z*~Vq|V=b-14-cu7r7Jvqu3Dyrs|Q-Uk7_bt)QXhvwa`USEbol?hM+=MggpWu>_8I? zk*die!0>k4Ob7zLRF@9Z4FMosOLOLSFptTe11;wh2pi-{gLt4on_UU^|GCERA1#WWp))$aNS?Nv|wQs)3&YbclDeRt|_eAj6a~nx1 zaLp|!VfV7=+@VgLTg)R}y!rj@#mxy*Fwxe#wZ|S9hC+PRj}_;o$^t#T?Ez>rDiRbysn@4ucwcOv1{QB*LOt zbfpkcd{v?=nATp()#vY8xk07LcAMnsKk8yPtX{)gQe^U#H8NM?aPyR>Vq3wKFU^cZbr{?&?4Km8Y(ZB9I+jvo%*RXudTsuVTm(!ZS zziLKsP@ZISJeYiNKliC0hC^hCgzXTo9sNNUIVlW%^v> z2;2#$`m+@Hqq{b1X>tD*bOBq05{D6(z!mx z2i(qb1!62Du4RPi{YfkmiTBq}K2)FEL`dLz$Ke}z?nyrZFpdE<0vf3vTJgHk-3K)V zY~3Ql6*jaHd+}GMIo&|rI&ZLIbvzcmpj?jAllBRtPT9Rfl4o*_i;V#gMm7SgO9Qtd zZuJqL5_ln`hV}2N39&LB@mDp16kBRnmRTdCEhR{ro%G-e#4?cYel+wyS3p8VK_?U_mkn2n}v9i4zeWt1`9rmo{fOF%Fh!_qIRToaed#5@^w%@a9jK#C)efa*M{+ZC(m=?G0S zTHpCO@#je6p7XWGQ;0{{9h#ozwTs1TdZV%2Q2Hs7sAy3j^_o`dnPXIEmLcjGsd%

~~#{F))Hs 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 delta 13793 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