Bir daire yanılsama animasyonu yapın


84

Sizin işiniz bu çevre ilüzyonunu canlandırmak . Dairenin içinde dönen noktalara benziyor, ama aslında sadece düz çizgiler halinde hareket ediyorlar.

görüntü tanımını buraya girin

kriterler

  • Sonuç canlandırılmalıdır. Animasyonu yapma şekliniz alakasız, bir üretebilir .gif, bir pencereye, bazı cihaz ekranına veya her neyse çizebilir.
  • Bu bir popülerlik yarışmasıdır, dolayısıyla daha fazla oy almak için programınıza bazı özellikler eklemek isteyebilirsiniz, örneğin puan sayısını değiştirebilirsiniz.
  • Kazanan, son geçerli gönderimden 7 gün sonra en çok oy alan geçerli cevaptır.
  • Aslında düz çizgiler üzerinde hareket eden noktaları uygulayacak cevaplar, başka bir yoldan değil, daha fazla memnuniyetle karşılanmaktadır.

"kazanan 7 gün sonra en çok oy alan geçerli" Öyleyse eğer birileri yıldızların ölümüne 6 günde bir ...
Kevin L,

3
@KevinL olması muhtemel değildir ve bu 15 fazladan birinin, 6 günde bir sorulan bu sorudan elde edeceğiniz tüm puanlarla karşılaştırıldığında çok önemli olduğunu sanmıyorum.
Martin Ender

1
Bazen bazılarının bunu sadece bir işi
bitirmek için

3
“Çemberin içinde dönen noktalar gibi görünüyor, ancak aslında sadece düz çizgiler halinde hareket ediyorlar.”, Veya, belki de bir daire içinde gerçekten
dönüyorlar

1
.. Bu animasyonu alamıyorum .. aklımdan .. özellikle 3-nokta versiyonu!
Thomas,

Yanıtlar:


126

Python 3.4

Kaplumbağa modülünü kullanma. Kaplumbağalar farklı renklerdir ve her zaman aynı yöne bakarlar, böylece sadece bir tanesine odaklanarak düz çizgiler boyunca hareket ettiği kolayca görülebilir. Buna rağmen daire yanılsaması hala güçlüdür.

11 kaplumbağalar

İllüzyon hala sadece 3 veya 4 kaplumbağa ile oldukça güçlü görünüyor:

3 kaplumbağalar4 kaplumbağalar

Bu GIF örnekleri için kare hızı önemli ölçüde azaltılmıştır, ancak illüzyondan uzaklaştığı görülmemektedir. Kodu yerel olarak çalıştırmak daha yumuşak bir animasyon verir.

import turtle
import time
from math import sin, pi
from random import random


def circle_dance(population=11, resolution=480, loops=1, flip=0, lines=0):
    population = int(population)
    resolution = int(resolution)
    radius = 250
    screen = turtle.Screen()
    screen.tracer(0)
    if lines:
        arrange_lines(population, radius)
    turtles = [turtle.Turtle() for i in range(population)]
    for i in range(population):
        dancer = turtles[i]
        make_dancer(dancer, i, population)
    animate(turtles, resolution, screen, loops, flip, radius)


def arrange_lines(population, radius):
    artist = turtle.Turtle()
    for n in range(population):
        artist.penup()
        artist.setposition(0, 0)
        artist.setheading(n / population * 180)
        artist.forward(-radius)
        artist.pendown()
        artist.forward(radius * 2)
    artist.hideturtle()


def make_dancer(dancer, i, population):
    dancer.setheading(i / population * 180)
    dancer.color(random_turtle_colour())
    dancer.penup()
    dancer.shape('turtle')
    dancer.turtlesize(2)


def random_turtle_colour():
    return random() * 0.9, 0.5 + random() * 0.5, random() * 0.7


def animate(turtles, resolution, screen, loops, flip, radius):
    delay = 4 / resolution      # 4 seconds per repetition
    while True:
        for step in range(resolution):
            timer = time.perf_counter()
            phase = step / resolution * 2 * pi
            draw_dancers(turtles, phase, screen, loops, flip, radius)
            elapsed = time.perf_counter() - timer
            adjusted_delay = max(0, delay - elapsed)
            time.sleep(adjusted_delay)


def draw_dancers(turtles, phase, screen, loops, flip, radius):
    population = len(turtles)
    for i in range(population):
        individual_phase = (phase + i / population * loops * pi) % (2*pi)
        dancer = turtles[i]
        if flip:
            if pi / 2 < individual_phase <= 3 * pi / 2:
                dancer.settiltangle(180)
            else:
                dancer.settiltangle(0)
        distance = radius * sin(individual_phase)
        dancer.setposition(0, 0)
        dancer.forward(distance)
    screen.update()


if __name__ == '__main__':
    import sys
    circle_dance(*(float(n) for n in sys.argv[1:]))

Bunun aksine, burada gerçekten dönen bazı şeyler var:

23 döngü kaplumbağalar23 adet kaplumbağa

... ya onlar?

Kod, isteğe bağlı 5 argümanla çalıştırılabilir: popülasyon, çözünürlük, döngüler, çevirme ve satırlar.

  • population kaplumbağa sayısı
  • resolution zaman çözünürlüğüdür (tekrar başına animasyon karelerinin sayısı)
  • loopskaplumbağaların kaç kez kendilerine döndüğünü belirler. 1'in varsayılanı standart bir daire verir, diğer tek sayılar kaplumbağalar dizisindeki bu ilmek sayısını verirken, sayılar uçlarda bağlantısı kesilmiş bir kaplumbağa dizisi verir, ancak yine de kavisli hareket yanılsaması ile.
  • flipeğer sıfır olmayanlar, kaplumbağaların dönüş yolculukları için yönlerini çevirmelerine neden olursa ( aslum tarafından önerildiği gibi, asla geriye doğru hareket etmemelerini sağlar). Varsayılan olarak, uç noktalarda görsel dikkat dağılmasından kaçınmak için sabit bir yön korurlar.
  • lines Sıfır olmayanlar, söz konusu örnek resimle tutarlılık için kaplumbağaların üzerinde hareket ettiği çizgileri görüntülerse.

Kümeli ve flipKümesiz Örnekler lines. Sporadik sıçramayı tercih etmemeyi tercih ettiğim için ana örneğimi yukarı çevirmeden bıraktım, ancak dairenin kenarı tüm kaplumbağalarla aynı hizada görünüyor, bu nedenle insanların koşarken tercih ettikleri tarzı seçmeleri için bir seçenek var. kod.

Kapaklı ve çizgili 11 kaplumbağaKapaklı 11 kaplumbağa

Yukarıdaki resimlerin aynı koddan nasıl üretildiği hemen belli olmayabilir. Özellikle yavaş bir dış döngü ve hızlı bir iç döngü (birinin yanlışlıkla düşürdüğü bir kardioid gibi görünen) olan görüntü. Birinin deney yaparken / düşünürken öğrenmeyi geciktirmek istemesi durumunda, bunun açıklamalarını aşağıda sakladım.

Farklı boyutlarda bir iç ve dış döngüye sahip animasyon, döngü sayısını 15'e ayarlayarak ve kaplumbağa sayısını 23'te bırakarak (15 döngüyü temsil etmek için çok düşük) yaratıldı. Çok sayıda kaplumbağa kullanılması, 15 açıkça tanımlanmış döngüye neden olur. Çok az kaplumbağa kullanılması, takma işlemle sonuçlanır (görüntü işleme ve görüntülemeyle aynı nedenle). Çok yüksek bir frekansı temsil etmeye çalışmak, bozulma ile birlikte daha düşük bir frekansın görüntülenmesine neden olur.

Farklı sayıları denemek için bu çarpıklıkların bazılarını simetrik orijinallerden daha ilginç buldum, bu yüzden buraya bir tane eklemek istedim ...


18
Kaplumbağaları severim.
FreeAsInBeer

18
Ben kaplumbağalar için +1
koştum

@ProgramFOX sözdizimi vurgulama için teşekkürler! Yardım ve metalar arasında arama yaptım ve kendimi ikna ettim, kod golfünü vurgulayan sözdizimimiz yoktu - şimdi bununla daha mutluyum.
trichoplax

1
@aslum bunu yapmak için basit bir değişiklik olurdu, ama yönlendirmelerinin donuk bir çizgide ilerlemekten sapmadıklarını vurgulamak istemelerini istedim. Belki de koda bir seçenek olarak eklemeliyim ki insanlar tercih ettikleri yaklaşımı seçebilsinler.
trichoplax

4
+1 - Bir bando grubunun bu eğlenceli olanlardan bazılarını yaptığını görmek harika olurdu!
mkoistinen

96

C

Sonuç:

görüntü tanımını buraya girin

#include <stdio.h>
#include <Windows.h>
#include <Math.h>

int round (double r) { return (r > 0.0) ? (r + 0.5) : (r - 0.5); }
void print (int x, int y, char c) {
    COORD p = { x, y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), p);
    printf("%c", c);
}

int main ()
{
    float pi = 3.14159265358979323846;
    float circle = pi * 2;
    int len = 12;
    int hlen = len / 2;
    int cx = 13;
    int cy = 8;
    float w = 11.0;
    float h =  8.0;
    float step = 0.0;

    while (1)
    {
        system("cls"); // xD

        for (int i = 0; i < len; i++)
        {
            float a = (i / (float)len) * circle;
            int x = cx + round(cos(a) * w);
            int y = cy + round(sin(a) * h);
            print(x, y, 'O');

            if (i < hlen) continue;

            step -= 0.05;
            float range = cos(a + step);
            x = cx + round(cos(a) * (w - 1) * range);
            y = cy + round(sin(a) * (h - 1) * range);
            print(x, y, 'O');
        }

        Sleep(100);
    }

    return 0;
}

3
Bazı karelerde biraz kapalı. Ancak ASCII'de yaptığınız için tebrikler!
justhalf

10
ASCII için +1 vesystem("cls"); // xD
Christoph Böhmwalder

1
Bu güzel.
trichoplax

1
Bu, Linux üzerinde çalışıyor. (oldukça sefil olmasına rağmen)
user824294

Zorunlu yorum: "Bu C değil! Standart Sleep, COORD veya SetConsoleCursorPosition! 'I tanımlamıyor!"
immibis

52

SVG (Javascript yok)

JSFiddle burada link

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 380 380" width="380" height="380" version="1.0">
  <g transform="translate(190 190)">
    <circle cx="0" cy="0" r="190" fill="#000"/>
    <line x1="0" y1="-190" x2="0" y2="190" stroke="#fff" stroke-width="1.5"/>
    <line x1="72.71" y1="175.54" x2="-72.71" y2="-175.54" stroke="#fff" stroke-width="1.5"/>
    <line x1="134.35" y1="134.35" x2="-134.35" y2="-134.35" stroke="#fff" stroke-width="1.5"/>
    <line x1="175.54" y1="72.71" x2="-175.54" y2="-72.71" stroke="#fff" stroke-width="1.5"/>
    <line x1="190" y1="0" x2="-190" y2="0" stroke="#fff" stroke-width="1.5"/>
    <line x1="175.54" y1="-72.71" x2="-175.54" y2="72.71" stroke="#fff" stroke-width="1.5"/>
    <line x1="134.35" y1="-134.35" x2="-134.35" y2="134.35" stroke="#fff" stroke-width="1.5"/>
    <line x1="72.71" y1="-175.54" x2="-72.71" y2="175.54" stroke="#fff" stroke-width="1.5"/>
    <g transform="rotate(0)">
      <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0" to="360" begin="0" dur="8s" repeatCount="indefinite"/>
      <g transform="translate(0 90)">
        <g transform="rotate(0)">
          <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0" to="-360" begin="0" dur="4s" repeatCount="indefinite"/>
          <circle cx="0" cy="90" r="10" fill="#fff"/>
          <circle cx="63.64" cy="63.64" r="10" fill="#fff"/>
          <circle cx="90" cy="0" r="10" fill="#fff"/>
          <circle cx="63.64" cy="-63.64" r="10" fill="#fff"/>
          <circle cx="0" cy="-90" r="10" fill="#fff"/>
          <circle cx="-63.64" cy="-63.64" r="10" fill="#fff"/>
          <circle cx="-90" cy="0" r="10" fill="#fff"/>
          <circle cx="-63.64" cy="63.64" r="10" fill="#fff"/>
        </g>
      </g>
    </g>
  </g>
</svg>

Hmmm, bunun kurallara uymadığından eminim, ama ben şahsen, aslında tam tersini yaptığınızı hayal kırıklığına uğrattım. “Noktalar dairenin içinde dönüyormuş gibi görünüyor, ama aslında sadece düz çizgiler halinde hareket ediyorlar ” yerine, sizinkiler: “Noktalar düz çizgiler halinde hareket ediyor gibi görünüyor, ancak aslında sadece dairenin içinde
dönüyorum

En yumuşak cevap!
Derek,

14
@mkoistinen Ne demek istediğinizi anlıyorum, ancak noktalar gerçekten düz çizgiler halinde hareket ediyor. Sadece iki rotasyonla pozisyonlarını hesaplamak daha kolay olacak :-)
squeamish ossifrage

Hepsini 'el ile mi yaptınız veya herhangi bir (metin dışı) editör kullandınız mı?
kusur

5
@flawr Numaraları bulmak için telefonumdaki düz metin editörünü ve hesap makinesini kullandım :-)
squeamish ossifrage

47

http://jsfiddle.net/z6vhD/13/

intervaltimeFPS'yi değiştirir (FPS = 1000 / intervaltime).
balls# topları değiştirir.
maxstepBir döngüdeki # basamaklarını ayarlar, 'pürüzsüz' büyüdükçe. 64 düzgün göründüğü yerde yeterince büyük olmalıdır.

Topları çizgiler boyunca hareket ettirmek yerine hareketli bir daire şeklinde modellenmiş, ancak görsel efekt aynı olmalı (?). Kodun bazıları oldukça ayrıntılı, ama bu kod golf değil, bu yüzden ...

var intervalTime = 40;
var balls = 8;
var maxstep = 64;

var canvas = $('#c').get(0); // 100% necessary jquery
var ctx = canvas.getContext('2d');
var step = 0;

animateWorld = function() {
    createBase();
    step = step % maxstep;
    var centerX = canvas.width/2 + 115 * Math.cos(step * 2 / maxstep * Math.PI);
    var centerY = canvas.height/2 + 115 * Math.sin(step * 2 / maxstep * Math.PI);

    for (var i=0; i<balls; i++) {
        drawCircle(ctx, (centerX + 115 * Math.cos((i * 2 / balls - step * 2 / maxstep) * Math.PI)), (centerY + 115 * Math.sin((i * 2 / balls - step * 2 / maxstep) * Math.PI)), 10, '#FFFFFF');     
    }

    step++;
}

function createBase() {
    drawCircle(ctx, canvas.width/2, canvas.height/2, 240, '#000000');
    for(var i=0; i<balls*2; i++) {
        drawLine(ctx, canvas.width/2, canvas.height/2, canvas.width/2 + 240 * Math.cos(i / balls * Math.PI), canvas.height/2 + 240 * Math.sin(i / balls * Math.PI), '#FFFFFF');
    }
}

function drawLine(context, x1, y1, x2, y2, c) {
    context.beginPath();
    context.moveTo(x1,y1);
    context.lineTo(x2,y2);
    context.lineWidth = 3;
    context.strokeStyle = c;
    context.stroke();
}

function drawCircle(context, x, y, r, c) {
    context.beginPath();
    context.arc(x, y, r, 0, 2*Math.PI);
    context.fillStyle = c;
    context.fill();
}

function drawRect(context, x, y, w, h, c) {
    context.fillStyle = c;
    context.fillRect(x, y, w, h);
}

$(document).ready(function() {
    intervalID = window.setInterval(animateWorld, intervalTime);
});

2
Çok pürüzsüz! Çok hoş.
nneonneo

5
SetInterval'i animasyonlar için kullanmayın, requestAnimationFrameonun yerine al . JSFiddle Modifiye kullanarak requestAnimationFrame.
klingt.net

1
Sadece birkaç parametre ayarlamasıyla çok farklı bir şey elde edersiniz .
FreeAsInBeer

@KevinL Yep, bunu da fark ettim. Güncellenmiş.
FreeAsInBeer

1
@FreeAsInBeer Oh, çok farklı bir şey söylediğinde, jsfiddle.net/z6vhD/100
Kevin L

41

CSS animasyonları

Yalnızca css animasyonlarını kullanan bir çözüm ( JSFiddle'daki animasyonu inceleyin - tarayıcıya en son sürümlerde çalışabilmesi için tarayıcıya belirli önekleri eklediğimi unutmayın).

<body>
    <div id="w1"></div>
    <div id="w2"></div>
    <div id="w3"></div>
    <div id="w4"></div>
    <div id="w5"></div>
    <div id="w6"></div>
    <div id="w7"></div>
    <div id="w8"></div>
</body>


div {
    position: absolute;
    width: 20px;
    height: 20px;
    border-radius: 20px;
    background: red;
    animation-duration: 4s;
    animation-iteration-count: infinite;
    animation-direction: alternate;
    animation-timing-function: ease-in-out;
}

#w1 { animation-name: s1; animation-delay: 0.0s }
#w2 { animation-name: s2; animation-delay: 0.5s }
#w3 { animation-name: s3; animation-delay: 1.0s }
#w4 { animation-name: s4; animation-delay: 1.5s }
#w5 { animation-name: s5; animation-delay: 2.0s }
#w6 { animation-name: s6; animation-delay: 2.5s }
#w7 { animation-name: s7; animation-delay: 3.0s }
#w8 { animation-name: s8; animation-delay: 3.5s }

@keyframes s1 { from {top: 100px; left:   0px;} to {top: 100px; left: 200px;} } 
@keyframes s2 { from {top:  62px; left:   8px;} to {top: 138px; left: 192px;} } 
@keyframes s3 { from {top:  29px; left:  29px;} to {top: 171px; left: 171px;} } 
@keyframes s4 { from {top:   8px; left:  62px;} to {top: 192px; left: 138px;} } 
@keyframes s5 { from {top:   0px; left: 100px;} to {top: 200px; left: 100px;} } 
@keyframes s6 { from {top:   8px; left: 138px;} to {top: 192px; left:  62px;} } 
@keyframes s7 { from {top:  29px; left: 171px;} to {top: 171px; left:  29px;} } 
@keyframes s8 { from {top:  62px; left: 192px;} to {top: 138px; left:   8px;} } 

3
Fiddle, benim için en son Chrome'da
çalışmaz

1
@mkoistinen - Farklı tarayıcılarda çalışabilmesi için farklı önekler eklemelisiniz. ( -webkit-Webkit tabanlı ve -moz-Mozilla tabanlı için) İşte güncellenmiş öneklerle
Derek 朕 會 功夫

@mkoistinen Haklısın. Yeni keman gerekli tüm tarayıcı öneklerini ekler ve en son Chrome'da çalışır.
Howard,

Ham link metni kapanış parantezini kaçırıyor - düzeltmek istemeniz durumunda sizi bilgilendirmek için hala mükemmel bir şekilde kullanılabilir (6 karakterden daha az karakter değiştiremiyorum).
trichoplax

35

Mathematica

İşte oldukça basit bir sunum.

animateCircle[n_] := Animate[Graphics[
   Flatten@{
     Disk[],
     White,
     Map[
      (
        phase = #*2 \[Pi]/n;
        line = {Cos[phase], Sin[phase]};
        {Line[{-line, line}],
         Disk[Sin[t + phase]*line, 0.05]}
        ) &,
      Range[n]
      ]
     },
   PlotRange -> {{-1.1, 1.1}, {-1.1, 1.1}}
   ],
  {t, 0, 2 \[Pi]}
  ]

Eğer ararsanız animateCircle[32], 32 çizgi ve daireyle temiz bir animasyon elde edersiniz.

görüntü tanımını buraya girin

Mathematica'da tamamen pürüzsüz, ancak GIF için çerçevelerin sayısını biraz sınırlamak zorunda kaldım.

Şimdi, her satıra iki disk yerleştirirseniz ne olur? (Yani, Disk[-Sin[t + phase]*line, 0.05]içindeki listeye ekleyin Map.)

görüntü tanımını buraya girin

Bunları ayrıca 90 ° faz dışı bırakabilirsiniz ( Cosbunun yerine kullanın -Sin):

görüntü tanımını buraya girin


Muhtemelen değiştirmeniz gereken, ne demek istediğini hataları yapmak bilmem {t, 0, 2 \[Pi]}için {t, 0, 2 \[Pi] - 2 \[Pi]/60, 2 \[Pi]/60}orada iki özdeş çerçeveler olacak ve değişmeyecek şekilde Animatekarşı Table. O zaman GIF’i dışa aktarabileceksiniz.
homoseksüel

@swish Hayır, aslında orada bulunmayan garip ek çizgiler ve olması gerekmeyen yerlerdeki (ve asla gerçek sonucu olmadıkları yerlerde) diskler oluşturur Animate. TableYine de kullanmayı deneyeceğim .
Martin Ender

@swish Bu çalıştı. Dün böyle bir şey denediğimi sanıyordum ama görünüşe göre yapmadım.
Martin Ender

25

VBScript + VBA + Excel Pasta Grafiği

Bu, işlemcinizi biraz ağlatacak ancak güzel görünüyor ve teknik özelliklere göre çalıştığına inanıyorum. @ Fabricio'nun cevabını daire hareketi algoritmasını uygulamak için kılavuz olarak kullandım.

EDIT: Oluşturma hızını artırmak için bazı ayarlamalar yapıldı.

Pasta grafiğinin ekran görüntüsü

Kod:

'Open Excel
Set objX = CreateObject("Excel.Application")
objX.Visible = True
objX.Workbooks.Add

'Populate values
objX.Cells(1, 1).Value = "Lbl"
objX.Cells(1, 2).Value = "Amt"
For fillX = 2 to 17
    objX.Cells(fillX, 1).Value = "V"+Cstr(fillX-1)
    objX.Cells(fillX, 2).Value = "1"
Next

'Create pie
objX.Range("A2:B17").Select
objX.ActiveSheet.Shapes.AddChart.Select
With objX.ActiveChart
    .ChartType = 5 'pieChart
    .SetSourceData  objX.Range("$A$2:$B$17")
    .SeriesCollection(1).Select
End with    

'Format pie
With objX.Selection.Format
    .Fill.ForeColor.RGB = 0 'black
    .Fill.Solid
    .Line.Weight = 2
    .Line.Visible = 1
    .Line.ForeColor.RGB = 16777215 'white
End With

'animation variables
pi = 3.14159265358979323846
circle = pi * 2 : l  = 16.0
hlen = l / 2    : cx = 152.0
cy = 99.0       : w  = 90.0
h  = 90.0       : s  = 0.0
Dim posArry(7,1)

'Animate
While 1 
  For i = 0 to hlen-1
    a = (i / l) * circle
    range = cos(a + s)
    x = cx + cos(a) * w * range
    y = cy + sin(a) * h * range

    If whileInx = 1 Then 
        createOval x, y
    ElseIf whileInx = 2 Then 
        objX.ActiveChart.Legend.Select
    ElseIf whileInx > 2 Then
        ovalName = "Oval "+ Cstr(i+1)
        dx = x - posArry(i,0)
        dy = y - posArry(i,1)
        moveOval ovalName, dx, dy
    End if

    posArry(i,0) = x
    posArry(i,1) = y
  Next

  s=s-0.05
  wscript.Sleep 1000/60 '60fps
  whileInx = 1 + whileInx
Wend

'create circles
sub createOval(posX, posY)
    objX.ActiveChart.Shapes.AddShape(9, posX, posY, 10, 10).Select '9=oval
    objX.Selection.ShapeRange.Line.Visible = 0
    with objX.Selection.ShapeRange.Fill
       .Visible = 1
       .ForeColor.RGB = 16777215 'white
       .solid
    end with
end sub

'move circles
sub moveOval(ovalName, dx, dy)
    with objX.ActiveChart.Shapes(ovalName)      
        .IncrementLeft dx
        .IncrementTop  dy
    end with
end sub

81 numaralı satırda benim için çöküyor, hata 80070057, "verilen ada sahip öğe yok" ya da bunun gibi bir şey (Macarcadan çevrilmiş, bu yüzden kesin hata mesajını bilmiyorum).
marczellm

Szervusz, @marczellm. Grafiğin dışını "canlandırırken" tıkladığımda bu hatayı yeniden oluşturabilirim. Odaklanmasına izin vermelisin yoksa program hata verir. Aksi halde, bunun Office ile olan uyumsuzluğundan dolayı olabilir. Win7'de Office 2010'dayım.
comfortablydrei

Office 2007, Win7. Benim durumumda grafik hiç odaklanmıyor gibi görünüyor.
marczellm

21

Excel, 161 bayt

Excel

=2*PI()*(NOW()*24*60*60/A2-FLOOR(NOW()*24*60*60/A2,1))
=ROUND(7*SIN(A1),0)
=ROUND(5*SIN(A1+1*PI()/4),0)
=ROUND(7*SIN(A1+2*PI()/4),0)
=ROUND(5*SIN(A1+3*PI()/4),0)

A2 (periyot), tam bir 'devrim' için zamanı (saniye) belirler.

Çizgilerdeki her hücre, karşılık gelen çizginin değeriyle ilgili temel bir koşulludur. Örneğin, K2:

 =1*(A5=7)

Ve merkez hücre (K9):

=1*OR(A5=0,A6=0,A7=0,A8=0)

Sürekli yenilemeyi tetiklemek için rastgele bir hücrede 'delete' tuşunu basılı tutarak animasyonu zorlayın.

Bunun eski bir konu olduğunu biliyorum, ancak son zamanlardaki faaliyetler onu zirveye taşıdı ve bir nedenden ötürü çekici görünüyordu. Uzun zamandır pcg dinleyici, ilk kez arayan. Nazik olmak.


Vay canına, bunu Excel ile yapabilmeniz inanılmaz: D
Beta Decay

15

Sadece PSTricks ile eğlenmek için.

görüntü tanımını buraya girin

\documentclass[preview,border=12pt,multi]{standalone}
\usepackage{pstricks}

\psset{unit=.3}

% static point
% #1 : half of the number of points
% #2 : ith point
\def\x[#1,#2]{(3*cos(Pi/#1*#2))}
\def\y[#1,#2]{(3*sin(Pi/#1*#2))}

% oscillated point
% #1 : half of the number of points
% #2 : ith point
% #3 : time parameter
\def\X[#1,#2]#3{(\x[#1,#2]*cos(#3+Pi/#1*#2))}
\def\Y[#1,#2]#3{(\y[#1,#2]*cos(#3+Pi/#1*#2))}

% single frame
% #1 : half of the number of points
% #2 : time parameter
\def\Frame#1#2{%
\begin{pspicture}(-3,-3)(3,3)
    \pstVerb{/I2P {AlgParser cvx exec} bind def}%
    \pscircle*{\dimexpr3\psunit+2pt\relax}
    \foreach \i in {1,...,#1}{\psline[linecolor=yellow](!\x[#1,\i] I2P \y[#1,\i] I2P)(!\x[#1,\i] I2P neg \y[#1,\i] I2P neg)}
    \foreach \i in {1,...,#1}{\pscircle*[linecolor=white](!\X[#1,\i]{#2} I2P \Y[#1,\i]{#2} I2P){2pt}}   
\end{pspicture}}

\begin{document}
\foreach \t in {0,...,24}
{   
    \preview
    \Frame{1}{2*Pi*\t/25} \quad \Frame{2}{2*Pi*\t/25} \quad \Frame{3}{2*Pi*\t/25} \quad \Frame{5}{2*Pi*\t/25} \quad \Frame{10}{2*Pi*\t/25}
    \endpreview
}
\end{document}

11

Fortran

Her kare, Fortran gif modülünü kullanarak ayrı bir gif dosyası olarak oluşturulur: http://fortranwiki.org/fortran/show/writegif
Sonra, tek tek gifleri bir animasyonlu gif olarak birleştirmek için ImageMagick'i kullanarak biraz hile yapıyorum.

Fortran

GÜNCELLEME: Yeni = .true ayarlayın. aşağıdakileri almak için:

görüntü tanımını buraya girin

program circle_illusion

use, intrinsic :: iso_fortran_env, only: wp=>real64
use gif_util  !gif writing module from http://fortranwiki.org/fortran/show/writegif

implicit none

logical,parameter :: new = .false.

integer,parameter  :: n        = 500  !550  !size of image (square)     
real(wp),parameter :: rcircle  = n/2  !250  !radius of the big circle
integer,parameter  :: time_sep = 5    !deg

real(wp),parameter :: deg2rad = acos(-1.0_wp)/180.0_wp
integer,dimension(0:n,0:n):: pixel     ! pixel values
integer,dimension(3,0:3)  :: colormap  ! RGB 0:255 for colors 0:ncol    
real(wp),dimension(2)     :: xy
integer,dimension(2)      :: ixy
real(wp)                  :: r,t
integer                   :: i,j,k,row,col,m,n_cases,ang_sep
character(len=10)         :: istr

integer,parameter  :: black = 0
integer,parameter  :: white = 1
integer,parameter  :: red   = 2
integer,parameter  :: gray  = 3    
colormap(:,0) = [0,0,0]          !black
colormap(:,1) = [255,255,255]    !white
colormap(:,2) = [255,0,0]        !red
colormap(:,3) = [200,200,200]    !gray

if (new) then
    ang_sep = 5
    n_cases = 3
else
    ang_sep = 20
    n_cases = 0
end if

do k=0,355,time_sep

    !clear entire image:
    pixel = white      

    if (new) call draw_circle(n/2,n/2,black,n/2)  

    !draw polar grid:    
    do j=0,180-ang_sep,ang_sep
        do i=-n/2, n/2
            call spherical_to_cartesian(dble(i),dble(j)*deg2rad,xy)
            call convert(xy,row,col)
            if (new) then
                pixel(row,col) = gray
            else
                pixel(row,col) = black  
            end if  
        end do
    end do

    !draw dots:
    do m=0,n_cases
        do j=0,360-ang_sep,ang_sep
            r = sin(m*90.0_wp*deg2rad + (k + j)*deg2rad)*rcircle                
            t = dble(j)*deg2rad    
            call spherical_to_cartesian(r,t,xy)
            call convert(xy,row,col)
            if (new) then
                !call draw_circle(row,col,black,10)  !v2
                !call draw_circle(row,col,m,5)       !v2
                call draw_circle(row,col,white,10)   !v3
            else
                call draw_square(row,col,red)        !v1
            end if
        end do
    end do

    !write the gif file for this frame:        
    write(istr,'(I5.3)') k
    call writegif('gifs/test'//trim(adjustl(istr))//'.gif',pixel,colormap)

end do

!use imagemagick to make animated gif from all the frames:
! from: http://thanosk.net/content/create-animated-gif-linux
if (new) then
    call system('convert -delay 5 gifs/test*.gif -loop 0 animated.gif')
else
    call system('convert -delay 10 gifs/test*.gif -loop 0 animated.gif')
end if

!delete individual files:
call system('rm gifs/test*.gif')

contains

    subroutine draw_square(r,c,icolor)

    implicit none
    integer,intent(in) :: r,c  !row,col of center
    integer,intent(in) :: icolor

    integer,parameter :: d = 10 !square size

    pixel(max(0,r-d):min(n,r+d),max(0,c-d):min(n,c+d)) = icolor

    end subroutine draw_square

    subroutine draw_circle(r,c,icolor,d)

    implicit none
    integer,intent(in) :: r,c  !row,col of center
    integer,intent(in) :: icolor
    integer,intent(in) :: d  !diameter

    integer :: i,j

    do i=max(0,r-d),min(n,r+d)
        do j=max(0,c-d),min(n,c+d)
            if (sqrt(dble(i-r)**2 + dble(j-c)**2)<=d) &
                pixel(i,j) = icolor
        end do
    end do

    end subroutine draw_circle

    subroutine convert(xy,row,col)

    implicit none
    real(wp),dimension(2),intent(in) :: xy  !coordinates
    integer,intent(out) :: row,col

    row = int(-xy(2) + n/2.0_wp)
    col = int( xy(1) + n/2.0_wp)

    end subroutine convert

    subroutine spherical_to_cartesian(r,theta,xy)

    implicit none
    real(wp),intent(in) :: r,theta
    real(wp),dimension(2),intent(out) :: xy

    xy(1) = r * cos(theta)
    xy(2) = r * sin(theta)

    end subroutine spherical_to_cartesian

end program circle_illusion

1
Dikey ve yatay elemanlar için 'squish' etkisini seviyorum.
Portland Runner

11

Zorunlu C64 sürümü.

Favori emülatörünüzde kopyala ve yapıştır:

C64 sürümü

1 print chr$(147)
2 poke 53281,0
3 for p=0 to 7
5 x=int(11+(cos(p*0.78)*10)):y=int(12+(sin(p*0.78)*10))
6 poke 1024+x+(y*40),15
9 next p
10 for sp=2040 to 2047:poke sp,13:next sp
20 for i=0 to 62:read a:poke 832+i,a:next i
30 for i=0 to 7:poke 53287+i,i+1:next i
40 rem activate sprites
50 poke 53269,255
60 an=0.0
70 rem maincycle
75 teta=0.0:k=an
80 for i=0 to 7
90 px=cos(k)*64
92 s=i:x=px*cos(teta): y=px*sin(teta): x=x+100: y=y+137: gosub 210
94 teta=teta+0.392699
95 k=k+0.392699
96 next i
130 an=an+0.1
140 goto 70
150 end
200 rem setspritepos
210 poke 53248+s*2,int(x): poke 53249+s*2,int(y)
220 return
5000 data 0,254,0
5010 data 3,199,128
5020 data 7,0,64
5030 data 12,126,96
5040 data 25,255,48
5050 data 59,7,152
5060 data 52,1,200
5070 data 116,0,204
5080 data 120,0,100
5090 data 120,0,100
5100 data 120,0,100
5110 data 120,0,36
5120 data 104,0,36
5130 data 100,0,108
5140 data 54,0,72
5150 data 51,0,152
5160 data 25,131,16
5170 data 12,124,96
5180 data 4,0,64
5190 data 3,1,128
5200 data 0,254,0

10

Varsayılan ayarları farklı bir şeye çeviren kompakt bir javascript sürümü

http://jsfiddle.net/yZ3DP/1/

HTML:

<canvas id="c" width="400" height="400" />

JavaScript:

var v= document.getElementById('c');
var c= v.getContext('2d');
var w= v.width, w2= w/2;
var num= 28, M2= Math.PI*2, da= M2/num;
draw();
var bw= 10;
var time= 0;
function draw()
{
    v.width= w;
    c.beginPath();
    c.fillStyle= 'black';
    circle(w2,w2,w2);
    c.lineWidth= 1.5;
    c.strokeStyle= c.fillStyle= 'white';
    var a= 0;
    for (var i=0; i< num*2; i++){
        c.moveTo(w2,w2);
        c.lineTo(w2+Math.cos(a)*w2, w2+Math.sin(a)*w2);
        a+= da/2;
    }
    c.stroke();
    a= 0;
    for (var i=0; i< num; i++){
        circle(w2+Math.cos(a)*Math.sin(time+i*Math.PI/num)*(w2-bw), 
               w2+Math.sin(a)*Math.sin(time+i*Math.PI/num)*(w2-bw), bw);
        a+= da/2;
    }
    time+=0.03;
   requestAnimationFrame(draw);
}

function circle(x,y,r)
{
    c.beginPath();
    c.arc(x, y, r, 0, M2);
    c.fill();

}

2
Çörek yaptın mı ? Aslında animasyonunuz daha küçük noktalarla güzel görünür (deneyin bw=10). Lütfen kodunuzu göstermek için cevabınızı düzenleyin. Değiştirin: Eğer bunu yaparken Oh ve düzeltmeniz gereken bir hata var time+i*0.39*0.29olan time+i*Math.PI/numkoordinatlar arasında herhangi bir değere göre doğru bir şekilde hesaplanmasını böylece trigonometrik hesaplamalarda num. (PS burada JSFiddle Güncelleme codegolf.stackexchange.com Ve karşılama.)
alıngan ossifrage

Sadece farklı bir şey yapmak istedim (kaplumbağalar gibi). Codegolf'taki Newbie :) Oh, ve formül için teşekkür ederim: DI sadece aceleyle yaptı ve rastgele değerler denedi, doğru formüle ulaşmak için bir dakika durmadı: P
Diego

1
+1 Görsel bir eğlence için küçük bir değişiklik: http://jsfiddle.net/9TQrm/ veya http://jsfiddle.net/Wrqs4/1/
Portland Runner

4

Elm ile almam . Ben bu çözümü geliştirmek için PR'ları memnuniyetle kabul edecek bir acemiyim ( GitHub ):

görüntü tanımını buraya girin

Bu gönderimin gerçekten düz çizgiler üzerinde hareket eden noktalar olduğuna dikkat edin:

import Color exposing (..)
import Graphics.Collage exposing (..)
import Graphics.Element exposing (..)
import Time exposing (..)
import Window
import List exposing (..)
import AnimationFrame -- "jwmerrill/elm-animation-frame"
import Debug

-- CONFIG

size = 600
circleSize = 240
dotCount = 12
dotSize = 10
velocity = 0.01

-- MODEL

type alias Dot =
    { x : Float
    , angle : Float
    }

type alias State = List Dot

createDots : State
createDots = map createDot [ 0 .. dotCount - 1 ]

createDot : Int -> Dot
createDot index =
    let angle = toFloat index * pi / dotCount
    in { x = 0
       , angle = angle
       }

-- UPDATE

update : Time -> State -> State
update time dots = map (moveDot time) dots |> Debug.watch "Dots"

moveDot : Time -> Dot -> Dot
moveDot time dot =
  let t = velocity * time / pi
      newX = (-circleSize + dotSize) * cos(t + dot.angle)
  in { dot | x <- newX }

-- VIEW

view : State -> Element
view dots =
   let background = filled black (circle circleSize)
       dotLinePairs = map viewDotWithLine dots
   in collage size size (background :: dotLinePairs)

viewDotWithLine : Dot -> Form
viewDotWithLine dot =
  let dotView = viewDot dot
      lineView = createLineView
  in group [dotView , lineView] |> rotate dot.angle

viewDot : Dot -> Form
viewDot d = alpha 0.8 (filled lightOrange (circle dotSize)) |> move (d.x, 0)

createLineView : Form
createLineView = traced (solid white) (path [ (-size / 2.0, 0) , (size / 2.0, 0) ])

-- SIGNALS

main = Signal.map view (animate createDots)

animate : State -> Signal State
animate dots = Signal.foldp update dots time

time = Signal.foldp (+) 0 AnimationFrame.frame

4
Bu imleç beni iyi kandırdı ve benimki bile siyah ya da o büyüklükte değil.
cole,

2

Second Life LSL

animasyon kaplumbağa alfa görüntüsünün başlangıcı (resmi kaydetmek için aşağı sağ tıklayın)
turtle.png
kaplumbağa alfa görüntüsünün sonu (resmi kaydetmek için sağ üst tıklayın)

nesneyi
oluştur : Kök prim silindir boyutu <1, 1, 0.01> olun dilim 0.49, 0.51, renk < 0, 0, 0>
Bu silindir "8,1,1,1" tırnak (çok önemli olmadan) açıklamasını yapmak
bir silindir yapmak, adı da "silindir", renk <0.25, 0.25, 0.25> alfa 0.5
yinelenen cyl 48 kez
bir kutu oluşturun, "küre" olarak adlandırın, renkli <1, 1, 1> saydamlık 100 hariç üst saydamlık 0 hariç
, kaplumbağa dokunuzu kutunun yüzüne 0 koyun, kaplumbağanın yüzü + x
kutuyu 48 kez kopyalamalıdır
tüm kutuları ve silindirleri seçin, kök silindirini seçtiğinizden emin olun,bağlantı (kontrol L)

Bu 2 betiği köke yerleştirin:

//script named "dialog"
default
{
    state_entry()
    {

    }

    link_message(integer link, integer num, string msg, key id)
    {
        list msgs = llCSV2List(msg);
        key agent = (key)llList2String(msgs, 0);
        string prompt = llList2String(msgs, 1);
        integer chan = (integer)llList2String(msgs, 2);
        msgs = llDeleteSubList(msgs, 0, 2);
        llDialog(agent, prompt, msgs, chan);
    }
}

//script named "radial animation"
float interval = 0.1;
float originalsize = 1.0;
float rate = 5;
integer maxpoints = 48;
integer points = 23; //1 to 48
integer multiplier = 15;
integer lines;
string url = "https://codegolf.stackexchange.com/questions/34887/make-a-circle-illusion-animation/34891";

list cylinders;
list spheres;
float angle;
integer running;
integer chan;
integer lh;

desc(integer on)
{
    if(on)
    {
        string desc = 
            (string)points + "," +
            (string)multiplier + "," +
            (string)running + "," +
            (string)lines
            ;

        llSetLinkPrimitiveParamsFast(1, [PRIM_DESC, desc]);
    }
    else
    {
        list params = llCSV2List(llList2String(llGetLinkPrimitiveParams(1, [PRIM_DESC]), 0));
        points = (integer)llList2String(params, 0);
        multiplier = (integer)llList2String(params, 1);
        running = (integer)llList2String(params, 2);
        lines = (integer)llList2String(params, 3);
    }    
}

init()
{
    llSetLinkPrimitiveParamsFast(LINK_ALL_OTHERS, [PRIM_POS_LOCAL, ZERO_VECTOR, 
        PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 0]);
    integer num = llGetNumberOfPrims();
    integer i;
    for(i = 2; i <= num; i++)
    {
        string name = llGetLinkName(i);

        if(name == "cyl")
            cylinders += [i];
        else if(name == "sphere")
            spheres += [i];
    }  

    vector size = llGetScale();
    float scale = size.x/originalsize;

    float r = size.x/4;
    vector cylindersize = <0.01*scale, 0.01*scale, r*4>;
    float arc = 180.0/points;

    for(i = 0; i < points; i++)
    {
        float angle = i*arc;
        rotation rot = llEuler2Rot(<0, 90, 0>*DEG_TO_RAD)*llEuler2Rot(<0, 0, angle>*DEG_TO_RAD);

        integer cyl = llList2Integer(cylinders, i);
        integer sphere = llList2Integer(spheres, i);

        llSetLinkPrimitiveParamsFast(1, [PRIM_LINK_TARGET, cyl, PRIM_POS_LOCAL, ZERO_VECTOR, PRIM_ROT_LOCAL, rot, PRIM_SIZE, cylindersize, PRIM_COLOR, ALL_SIDES, <0.25, 0.25, 0.25>, 0.5*lines,
        PRIM_LINK_TARGET, sphere, PRIM_COLOR, ALL_SIDES, <0.25 + llFrand(0.75), 0.25 + llFrand(0.75), 0.25 + llFrand(0.75)>, 1
        ]);
    }
}

run()
{
    vector size = llGetScale();
    float scale = size.x/originalsize;

    float r = size.x/2;
    vector spheresize = <0.06, 0.06, 0.02>*scale;
    float arc = 180.0/points;
    list params;
    integer i;
    for(i = 0; i < points; i++)
    {

        float x = r*llCos((angle + i*arc*multiplier)*DEG_TO_RAD);

        vector pos = <x, 0, 0>*llEuler2Rot(<0, 0, i*arc>*DEG_TO_RAD);
        rotation rot = llEuler2Rot(<0, 0, i*arc>*DEG_TO_RAD);
        integer link = llList2Integer(spheres, i);
        params += [PRIM_LINK_TARGET, link, PRIM_POS_LOCAL, pos,  
            PRIM_ROT_LOCAL, rot,
            PRIM_SIZE, spheresize
            //PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 1
            ];
    }   

    llSetLinkPrimitiveParamsFast(1, params);
}

dialog(key id)
{
    string runningstring;
    if(running)
        runningstring = "notrunning";
    else
        runningstring = "running";

    string linesstring;
    if(lines)
        linesstring = "nolines";
    else
        linesstring = "lines";
    string prompt = "\npoints: " + (string)points + "\nmultiplier: " + (string)multiplier;
    string buttons = runningstring + ",points+,points-,reset,multiplier+,multiplier-," + linesstring + ",www";
    llMessageLinked(1, 0, (string)id + "," + prompt + "," + (string)chan + "," + buttons, "");
    //llDialog(id, prompt, llCSV2List(buttons), chan);
}

default
{
    state_entry()
    {
        chan = (integer)("0x" + llGetSubString((string)llGetKey(), -8, -1));
        lh = llListen(chan, "", "", "");

        desc(FALSE);
        init();
        run();
        llSetTimerEvent(interval);
    }

    on_rez(integer param)
    {
        llListenRemove(lh);
        chan = (integer)("0x" + llGetSubString((string)llGetKey(), -8, -1));
        lh = llListen(chan, "", "", "");
    }

    touch_start(integer total_number)
    {
        key id = llDetectedKey(0);
        dialog(id);
    }

    timer()
    {
        if(!running)
            return;

        angle += rate;
        if(angle > 360)
            angle -= 360;
        else if(angle < 0)
            angle += 360;

        run();
    }

    listen(integer channel, string name, key id, string msg)
    {
        if(msg == "points+")
        {
            if(points < maxpoints)
            {
                points++;
                desc(TRUE);
                llResetScript();            
            }
        }
        else if(msg == "points-")
        {
            if(points > 0)
            {
                points--;
                desc(TRUE);
                llResetScript();
            }
        }        
        else if(msg == "multiplier+")
        {
            multiplier++;
            desc(TRUE);
        }
        else if(msg == "multiplier-")
        {
            multiplier--;
            desc(TRUE);
        }
        else if(msg == "running")
        {
            running = TRUE;
            desc(TRUE);
        }
        else if(msg == "notrunning")
        {
            running = FALSE;
            desc(TRUE);
        }
        else if(msg == "lines")
        {
            lines = TRUE;
            desc(TRUE);
            llResetScript();
        }
        else if(msg == "nolines")
        {
            lines = FALSE;
            desc(TRUE);
            llResetScript();
        }
        else if(msg == "reset")
            llResetScript();
        else if(msg == "www")
            llRegionSayTo(id, 0, url);
        dialog(id);
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.