Utwórz zegar analogowy

24

Utwórz zegar analogowy

Cel: Utworzenie działającego zegara analogowego za pomocą dowolnego języka programowania.

Wymagania:

  • Twój zegar powinien zawierać co najmniej wskazówki godzinowe i minutowe.
  • Wytworzony zegar może mieć postać obrazu, animacji lub sztuki ASCII.
  • Oczekuje się, że zegar pokazuje czas lokalny.

Opcjonalny:

  • Możesz ustawić zegar tak, aby oprócz wskaźnika minut i godzin pokazywał wskaźnik sekund.
  • Możesz także skonfigurować strefę czasową, jeśli chcesz.
  • Masz swobodę wyboru, czy możesz zaniedbać lub rozwiązać problemy dotyczące sekund przestępnych.
  • Możesz pomyśleć o tym, co stanie się z twoim programem, jeśli użytkownik dostosuje zegar systemowy lub jeśli nastąpi zmiana światła dziennego.

Ponieważ jest to , bądź kreatywny i narysuj kilka ładnych i pięknych zegarów, które zasługują na poparcie. Najbardziej pozytywna odpowiedź wygrywa , z wyjątkiem tego, że nie zaakceptuję własnej odpowiedzi.

Na koniec zaleca się (ale nie jest to wymagane) opublikowanie co najmniej jednego zrzutu ekranu (lub tekstu w przypadku grafiki ASCII) zegara w odpowiedzi. W ten sposób ludzie nie będą musieli się kompilować i uruchamiać, aby zobaczyć, co to jest.


To pytanie ma być odrodzeniem usuniętego pytania.

Pamiętaj, że nie jest to kopia tego drugiego pytania . To pytanie dotyczyło z ASCII. Ten nie jest ograniczony do sztuki ASCII i jest , więc odpowiedzi powinny być bardzo różne.

Victor Stafusa
źródło
Moja skorupa rozwiązanie: xclock. Wymaga zainstalowania xclock.
juniorRubyist

Odpowiedzi:

31

SVG + JavaScript

Zrzut ekranu z zegarem analogowym SVG

▶szałek Live demo tutaj ◀◀◀

Wykorzystuje to wbudowane funkcje animacji SVG do obracania rąk, z odrobiną dodatkowego Javascript, aby pobrać czas lokalny i ustawić początkowe pozycje rąk. Działa OK w Chrome i Safari i powinien być kompatybilny z większością współczesnych przeglądarek, ponieważ nie używa żadnych efektów filtrów.

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400" width="400" height="400" version="1.0">
  <defs>
    <linearGradient id="a" x1="0%" y1="100%" x2="0%" y2="0%">
      <stop offset="0%" style="stop-color:#777799"/>
      <stop offset="100%" style="stop-color:#ffffff"/>
    </linearGradient>
    <linearGradient id="b" x1="0%" y1="100%" x2="0%" y2="0%">
      <stop offset="0%" style="stop-color:#ffffff"/>
      <stop offset="25%" style="stop-color:#b6b6cc"/>
      <stop offset="40%" style="stop-color:#515177"/>
      <stop offset="48%" style="stop-color:#ffffff"/>
      <stop offset="56%" style="stop-color:#ffffff"/>
      <stop offset="75%" style="stop-color:#8b8baa"/>
      <stop offset="98%" style="stop-color:#efeff4"/>
      <stop offset="100%" style="stop-color:#fbfbfc"/>
    </linearGradient>
    <linearGradient id="c" x1="0%" y1="100%" x2="0%" y2="0%">
      <stop offset="0%" style="stop-color:#ffffff"/>
      <stop offset="100%" style="stop-color:#777799"/>
    </linearGradient>
    <radialGradient id="d" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
      <stop offset="0%" style="stop-color:#ffffff"/>
      <stop offset="40%" style="stop-color:#ffffff"/>
      <stop offset="70%" style="stop-color:#e6e6ee"/>
      <stop offset="92%" style="stop-color:#b6b6cc"/>
      <stop offset="100%" style="stop-color:#636388"/>
    </radialGradient>
    <radialGradient id="e" cx="50%" cy="150%" r="200%" fx="50%" fy="150%">
      <stop offset="0%" style="stop-color:#ffffff;stop-opacity:0"/>
      <stop offset="59%" style="stop-color:#ffffff;stop-opacity:0"/>
      <stop offset="60%" style="stop-color:#ffffff;stop-opacity:0.6"/>
      <stop offset="70%" style="stop-color:#ffffff;stop-opacity:0.3"/>
      <stop offset="100%" style="stop-color:#ffffff;stop-opacity:0.0"/>
    </radialGradient>
  </defs>
  <g transform="translate(200 200)">
    <circle cx="0" cy="0" r="200" fill="#cecedd"/>
    <circle cx="0" cy="0" r="196" stroke="url(#a)" stroke-width="5" fill="url(#b)"/>
    <circle cx="0" cy="0" r="170" stroke="url(#c)" stroke-width="4" fill="url(#d)"/>
    <circle cx="0" cy="0" r="172" stroke="#ffffff" stroke-width="0.5" fill="none"/>
    <circle cx="0" cy="0" r="193.5" stroke="#ffffff" stroke-width="0.5" fill="none"/>
    <g id="O">
      <polygon points="4,155 4,130 -4,130 -4,155" style="fill:#777799;stroke:#313155;stroke-width:1"/>
      <polygon points="4,-155 4,-130 -4,-130 -4,-155" style="fill:#777799;stroke:#313155;stroke-width:1"/>
    </g>
    <g transform="rotate(30)"><use xlink:href="#O"/></g>
    <g transform="rotate(60)"><use xlink:href="#O"/></g>
    <g transform="rotate(90)"><use xlink:href="#O"/></g>
    <g transform="rotate(120)"><use xlink:href="#O"/></g>
    <g transform="rotate(150)"><use xlink:href="#O"/></g>
    <polygon id="h" points="6,-80 6,18 -6,18 -6,-80" style="fill:#232344">
      <animateTransform id="ht" attributeType="xml" attributeName="transform" type="rotate" from="000" to="000" begin="0" dur="86400s" repeatCount="indefinite"/>
    </polygon>
    <polygon id="m" points="3.5,-140 3.5,23 -3.5,23 -3.5,-140" style="fill:#232344">
      <animateTransform id="mt" attributeType="xml" attributeName="transform" type="rotate" from="000" to="000" begin="0" dur="3600s" repeatCount="indefinite"/>
    </polygon>
    <polygon id="s" points="2,-143 2,25 -2,25 -2,-143" style="fill:#232344">
      <animateTransform id="st" attributeType="xml" attributeName="transform" type="rotate" from="000" to="000" begin="0" dur="60s" repeatCount="indefinite"/>
    </polygon>
    <circle cx="0" cy="0" r="163" fill="url(#e)"/>
  </g>
  <script type="text/javascript"><![CDATA[
    var d = new Date();
    var s = d.getSeconds();
    var m = d.getMinutes() + s/60;
    var h = (d.getHours() % 12) + m/60 + s/3600;
    document.getElementById('st').setAttribute('from',s*6);
    document.getElementById('mt').setAttribute('from',m*6);
    document.getElementById('ht').setAttribute('from',h*30);
    document.getElementById('st').setAttribute('to',360+s*6);
    document.getElementById('mt').setAttribute('to',360+m*6);
    document.getElementById('ht').setAttribute('to',360+h*30);
  ]]></script>
</svg>
piskliwy kostuch
źródło
Łał! Wszystko, czego brakuje, aby wyglądać super-skeuomorficznie, to cienie pod rękami!
Wygląda dobrze z cieniami, ale animacja może być nieco niepoprawna w Chrome.
piskliwy skostnienie
1
Fajne. Nie miałem pojęcia, że ​​SVG mogą robić takie rzeczy.
Sebastian Negraszus
17

Java 8

Zrobiłem zegar, który zmienia kolory odpowiednio do pory dnia, pokazując czas lokalny. Z upływem czasu powoli zmienia kolory, używając jaśniejszych kolorów w dzień i ciemniejszych kolorów w nocy.

Rozmiar okna można zmienić, a zegar automatycznie zmieni rozmiar na dowolny wybrany rozmiar.

Ponadto, jeśli użytkownik dostosuje zegar systemowy lub nastąpi zmiana czasu w ciągu dnia, zegar automatycznie to odzwierciedli.

Istnieją dwie formy uruchomienia:

  1. Uruchamianie ClockDemopliku, tj java clock.ClockDemo. Otworzy się okno i zobaczysz tam zegar.

  2. Uruchamianie ClockSavepliku, tj java clock.ClockSave filename width height [HH:mm:ss]. To po prostu zapisze zegar w pliku PNG o podanej nazwie, szerokości i wysokości. Zegar będzie losowany z podanym czasem, a jeśli go pominięto, z bieżącym czasem. Na przykład, jeśli uruchomisz go, ponieważ java clock.ClockSave clock.png 600 500 12:38:24spowoduje zapisanie zegara na obrazie 600 x 500 w clock.pngpliku, a zegar pokaże 12:38:24 AM. Wykorzystuj godziny w przedziale 00-23.


Zrzuty ekranu

Oto kilka zrzutów ekranu i wygenerowanych plików:

00:36:50:

00:36:50

02:38:51 AM:

02:39:51 AM

06:42:13 AM:

06:42:13 AM

11:15:28:

11:15:28

05:02:37 PM:

05:02:37 PM

19:11:30:

07:11:30

09:29:34 PM:

09:29:34 PM


Kod źródłowy

Oddzieliłem źródło w pięciu różnych plikach w pakiecie o nazwie clock.

Dostępne również w GitHub .

ClockDemo.java

package clock;

import java.awt.EventQueue;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;

public class ClockDemo {
    public static void main(String[] args) {
        EventQueue.invokeLater(ClockDemo::runIt);
    }

    private static void runIt() {
        final JFrame j = new JFrame();
        j.setTitle("JClock");
        final JClock clock = new JClock(new CoolPaint());

        j.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                clock.stop();
                j.dispose();
            }
        });

        j.add(clock);
        j.setBounds(20, 20, 600, 500);
        j.setVisible(true);
        clock.start();
    }
}

ClockSave.java

package clock;

import java.io.IOException;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

public class ClockSave {
    public static void main(String[] args) {

        // Too much arguments.
        if (args.length < 3 || args.length > 4) {
            System.out.println("Bad usage: Should be java clock.ClockSave filename width height [HH:mm:ss]");
            return;
        }

        // Parse the image size.
        int h, w;
        try {
            w = Integer.parseInt(args[1]);
            h = Integer.parseInt(args[2]);
        } catch (NumberFormatException e) {
            System.out.println("Bad usage: Should be java clock.ClockSave filename width height [HH:mm:ss]");
            return;
        }

        // Parse the intended time.
        LocalTime time;
        if (args.length == 4) {
            try {
                DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm:ss");
                time = LocalTime.parse(args[3], df);
            } catch (DateTimeParseException e) {
                System.out.println("Bad usage: Should be java clock.ClockSave filename width height [HH:mm:ss]");
                return;
            }
        } else {
            time = LocalTime.now();
        }

        // Save to an image.
        try {
            new CoolPaint().saveClock(w, h, time, args[0]);
        } catch (IOException e) {
            System.out.println("Error on image output: " + e.getMessage());
        }
    }
}

JClock.java

package clock;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.time.LocalTime;
import java.time.temporal.ChronoField;
import javax.swing.JComponent;

public class JClock extends JComponent {
    private static final long serialVersionUID = 1L;

    private final CoolPaint paint;
    private final Object lock;
    private Thread updater;

    public JClock(CoolPaint paint) {
        this.paint = paint;
        this.lock = new Object();
    }

    private void runClock() {
        int lastTime = -1;
        try {
            while (isRunning()) {
                Thread.sleep(10);
                int t = time();
                if (t != lastTime) {
                    lastTime = t;
                    repaint();
                }
            }
        } catch (InterruptedException e) {
            // Do nothing, the thread will die naturally.
        }
    }

    private int time() {
        return LocalTime.now().get(ChronoField.SECOND_OF_DAY);
    }

    private boolean isRunning() {
        synchronized (lock) {
            return updater == Thread.currentThread();
        }
    }

    public void start() {
        synchronized (lock) {
            if (updater != null) return;
            updater = new Thread(this::runClock);
            updater.start();
        }
    }

    public void stop() {
        synchronized (lock) {
            updater = null;
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        paint.paintClock(getWidth(), getHeight(), time(), (Graphics2D) g);
    }
}

ClockPaint.java

package clock;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.time.LocalTime;
import java.time.temporal.ChronoField;
import javax.imageio.ImageIO;

public interface ClockPaint {

    public void paintClock(int width, int height, int seconds, Graphics2D g2);

    public default void paintClock(int width, int height, LocalTime time, Graphics2D g2) {
        paintClock(width, height, time.get(ChronoField.SECOND_OF_DAY), g2);
    }

    public default void paintClock(int width, int height, Graphics2D g2) {
        paintClock(width, height, LocalTime.now(), g2);
    }

    public default void saveClock(int width, int height, String fileName) throws IOException {
        saveClock(width, height, LocalTime.now(), fileName);
    }

    public default void saveClock(int width, int height, LocalTime time, String fileName) throws IOException {
        saveClock(width, height, time.get(ChronoField.SECOND_OF_DAY), fileName);
    }

    public default void saveClock(int width, int height, int seconds, String fileName) throws IOException {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        paintClock(width, height, seconds, (Graphics2D) image.getGraphics());
        String f = fileName.endsWith(".png") ? fileName : fileName + ".png";
        ImageIO.write(image, "png", new File(f));
    }
}

CoolPaint.java

package clock;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;

public class CoolPaint implements ClockPaint {

    private static final int SECONDS_IN_MINUTE = 60;
    private static final int SECONDS_IN_HALF_HOUR = 30 * SECONDS_IN_MINUTE;
    private static final int SECONDS_IN_HOUR = 60 * SECONDS_IN_MINUTE;
    private static final int SECONDS_IN_12_HOURS = 12 * SECONDS_IN_HOUR;

    private static final int AM_0_00 = 0;
    private static final int AM_3_00 = 3 * SECONDS_IN_HOUR;
    private static final int AM_4_30 = 4 * SECONDS_IN_HOUR + SECONDS_IN_HALF_HOUR;
    private static final int AM_7_30 = 7 * SECONDS_IN_HOUR + SECONDS_IN_HALF_HOUR;
    private static final int AM_12_00 = 12 * SECONDS_IN_HOUR;
    private static final int PM_4_30 = 16 * SECONDS_IN_HOUR + SECONDS_IN_HALF_HOUR;
    private static final int PM_7_30 = 19 * SECONDS_IN_HOUR + SECONDS_IN_HALF_HOUR;
    private static final int PM_9_00 = 21 * SECONDS_IN_HOUR;
    private static final int PM_12_00 = 24 * SECONDS_IN_HOUR;

    private static final Color BLACK = new Color(0, 0, 0);
    private static final Color DARK_GRAY = new Color(32, 32, 32);
    private static final Color DARK_BLUE = new Color(0, 0, 128);
    private static final Color PURPLE = new Color(128, 0, 128);
    private static final Color CYAN = new Color(0, 255, 255);
    private static final Color YELLOW = new Color(225, 225, 0);
    private static final Color PALE_YELLOW = new Color(224, 224, 64);
    private static final Color RED = new Color(255, 0, 0);
    private static final Color GREEN = new Color(0, 255, 0);
    private static final Color LIGHT_BLUE = new Color(128, 128, 255);
    private static final Color SKY_CYAN = new Color(48, 224, 224);

    private static final Color[] COLOR_CYCLE = {
        DARK_GRAY, LIGHT_BLUE, RED, PALE_YELLOW, GREEN, SKY_CYAN, LIGHT_BLUE, DARK_GRAY
    };

    private static final int RADIAL_PERIOD_LENGTH = PM_12_00 / COLOR_CYCLE.length;
    private static final String[] ROMAN = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"};

    private static class Painter {
        private final int width;
        private final int height;
        private final int seconds;
        private final int radius;
        private final Graphics2D g2;
        private final int cx;
        private final int cy;
        private final int secondColorIndex;
        private final int secondsInPeriod;
        private final Color pointersAndNumbersColor;

        public Painter(int width, int height, int seconds, Graphics2D g2) {
            this.width = width;
            this.height = height;
            this.seconds = seconds;
            this.radius = Math.min(width / 2, height / 2);
            this.cx = width / 2;
            this.cy = height / 2;
            this.g2 = g2;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            this.secondColorIndex = seconds / RADIAL_PERIOD_LENGTH;
            this.secondsInPeriod = seconds % RADIAL_PERIOD_LENGTH;

            int startIndex = (secondColorIndex + COLOR_CYCLE.length + 5) % COLOR_CYCLE.length;
            int endIndex = (secondColorIndex + COLOR_CYCLE.length + 6) % COLOR_CYCLE.length;
            Color color1 = COLOR_CYCLE[startIndex];
            Color color2 = COLOR_CYCLE[endIndex];
            this.pointersAndNumbersColor = mixColors(color1, color2, 0, RADIAL_PERIOD_LENGTH, secondsInPeriod);
        }

        private int mixColorComponent(int startComponent, int endComponent, double position) {
            int difference = endComponent - startComponent;
            return startComponent + (int) (difference * position);
        }

        private Color mixColors(Color startColor, Color endColor, int startTime, int endTime, int currentTime) {
            double normalized = (currentTime - startTime) / (double) (endTime - startTime);
            return new Color(
                    mixColorComponent(startColor.getRed(), endColor.getRed(), normalized),
                    mixColorComponent(startColor.getGreen(), endColor.getGreen(), normalized),
                    mixColorComponent(startColor.getBlue(), endColor.getBlue(), normalized));
        }

        private Color upperBackgroundColor() {
            if (seconds < 0) throw new IllegalArgumentException();
            if (seconds <= AM_3_00) return BLACK;
            if (seconds <= AM_4_30) return mixColors(BLACK, DARK_BLUE, AM_3_00, AM_4_30, seconds);
            if (seconds <= AM_7_30) return mixColors(DARK_BLUE, CYAN, AM_4_30, AM_7_30, seconds);
            if (seconds <= AM_12_00) return CYAN;
            if (seconds <= PM_4_30) return CYAN;
            if (seconds <= PM_7_30) return mixColors(CYAN, DARK_BLUE, PM_4_30, PM_7_30, seconds);
            if (seconds <= PM_9_00) return mixColors(DARK_BLUE, BLACK, PM_7_30, PM_9_00, seconds);
            if (seconds <= PM_12_00) return BLACK;
            throw new IllegalArgumentException();
        }

        private Color lowerBackgroundColor() {
            if (seconds < 0) throw new IllegalArgumentException();
            if (seconds <= AM_3_00) return mixColors(BLACK, DARK_BLUE, AM_0_00, AM_3_00, seconds);
            if (seconds <= AM_4_30) return mixColors(DARK_BLUE, PURPLE, AM_3_00, AM_4_30, seconds);
            if (seconds <= AM_7_30) return mixColors(PURPLE, YELLOW, AM_4_30, AM_7_30, seconds);
            if (seconds <= AM_12_00) return mixColors(YELLOW, CYAN, AM_7_30, AM_12_00, seconds);
            if (seconds <= PM_4_30) return mixColors(CYAN, YELLOW, AM_12_00, PM_4_30, seconds);
            if (seconds <= PM_7_30) return mixColors(YELLOW, PURPLE, PM_4_30, PM_7_30, seconds);
            if (seconds <= PM_9_00) return mixColors(PURPLE, DARK_BLUE, PM_7_30, PM_9_00, seconds);
            if (seconds <= PM_12_00) return mixColors(DARK_BLUE, BLACK, PM_9_00, PM_12_00, seconds);
            throw new IllegalArgumentException();
        }

        private void paintBackground() {
            Point2D p1 = new Point2D.Double(width / 2, 0);
            Point2D p2 = new Point2D.Double(width / 2, height);
            g2.setPaint(new GradientPaint(p1, upperBackgroundColor(), p2, lowerBackgroundColor()));
            g2.fillRect(0, 0, width, height);
        }

        private RadialGradientPaint colorOnCycle(Point2D center, float radius) {
            Color baseColor1 = COLOR_CYCLE[(secondColorIndex + COLOR_CYCLE.length - 1) % COLOR_CYCLE.length];
            Color baseColor2 = COLOR_CYCLE[secondColorIndex];
            Color baseColor3 = COLOR_CYCLE[(secondColorIndex + COLOR_CYCLE.length + 1) % COLOR_CYCLE.length];
            Color baseColor4 = COLOR_CYCLE[(secondColorIndex + COLOR_CYCLE.length + 2) % COLOR_CYCLE.length];

            Color start = mixColors(baseColor1, baseColor2, 0, RADIAL_PERIOD_LENGTH, secondsInPeriod);
            Color end = mixColors(baseColor3, baseColor4, 0, RADIAL_PERIOD_LENGTH, secondsInPeriod);
            float index2 = (RADIAL_PERIOD_LENGTH - secondsInPeriod) / (float) RADIAL_PERIOD_LENGTH / 2;
            float index3 = 0.5f + index2;
            float[] positions = index3 == 1.0 ? new float[] {0.0f, index2, 1.0f}
                    : new float[] {0.0f, index2, index3, 1.0f};
            Color[] colors = index3 == 1.0 ? new Color[] {start, baseColor2, end}
                    : new Color[] {start, baseColor2, baseColor3, end};

            return new RadialGradientPaint(center, radius, positions, colors);
        }

        private void paintClockArea() {
            Point2D center = new Point2D.Double(width / 2, height / 2);
            g2.setPaint(colorOnCycle(center, radius));
            g2.fillOval(width / 2 - radius, height / 2 - radius, radius * 2, radius * 2);
        }

        private double pointerRevolutionsToRadians(double angle) {
            return Math.toRadians((450 + angle * -360) % 360.0);
        }

        private void paintPointers() {
            double hAngle = pointerRevolutionsToRadians(seconds % SECONDS_IN_12_HOURS / (double) SECONDS_IN_12_HOURS);
            double mAngle = pointerRevolutionsToRadians(seconds % SECONDS_IN_HOUR / (double) SECONDS_IN_HOUR);
            double sAngle = pointerRevolutionsToRadians(seconds % SECONDS_IN_MINUTE / (double) SECONDS_IN_MINUTE);

            g2.setStroke(new BasicStroke(4.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2.drawLine(cx, cy, (int) (cx + Math.cos(hAngle) * radius * 0.55), (int) (cy - Math.sin(hAngle) * radius * 0.55));
            g2.drawLine(cx, cy, (int) (cx + Math.cos(mAngle) * radius * 0.85), (int) (cy - Math.sin(mAngle) * radius * 0.85));
            g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2.drawLine(cx, cy, (int) (cx + Math.cos(sAngle) * radius * 0.85), (int) (cy - Math.sin(sAngle) * radius * 0.85));
        }

        private void paintNumbers() {
            Font originalFont = g2.getFont();
            double amplification = (int) Math.max(radius * 0.08, originalFont.getSize()) / (double) originalFont.getSize();
            AffineTransform at0 = AffineTransform.getScaleInstance(amplification, amplification);
            Font amplifiedFont = originalFont.deriveFont(at0);
            g2.setFont(amplifiedFont);
            FontMetrics fm = g2.getFontMetrics();

            for (int i = 1; i <= 12; i++) {
                double angle = pointerRevolutionsToRadians(i / 12.0);
                double textInclination = Math.toRadians(30 * i);
                AffineTransform at = AffineTransform.getRotateInstance(textInclination);
                at.scale(amplification, amplification);
                Font derivedFont = originalFont.deriveFont(at);
                g2.setFont(derivedFont);
                int pixelsOffset = fm.stringWidth(ROMAN[i]) / 2;
                int xPlot = (int) (cx + Math.cos(angle) * radius * 0.9 - pixelsOffset * Math.cos(textInclination));
                int yPlot = (int) (cy - Math.sin(angle) * radius * 0.9 - pixelsOffset * Math.sin(textInclination));
                g2.drawString(ROMAN[i], xPlot, yPlot);
            }
            g2.setFont(originalFont);
        }

        private void paintDots() {
            for (int i = 1; i < 60; i++) {
                if (i % 5 == 0) continue;
                double angle = pointerRevolutionsToRadians(i / 60.0);
                g2.fillRect((int) (cx + Math.cos(angle) * radius * 0.9) - 1, (int) (cy - Math.sin(angle) * radius * 0.9) - 1, 3, 3);
            }
        }

        public void paintClock() {
            paintBackground();
            paintClockArea();

            g2.setColor(pointersAndNumbersColor);
            g2.setPaint(pointersAndNumbersColor);
            paintNumbers();
            paintDots();
            paintPointers();
        }
    }

    @Override
    public void paintClock(int width, int height, int seconds, Graphics2D g2) {
        new Painter(width, height, seconds, g2).paintClock();
    }
}
Victor Stafusa
źródło
Sfrustrowały mnie różne zegary na pulpicie (potrzebuję jednego :)), więc postanowiłem użyć kodu jako podstawy prostego zegara. Czy przypadkiem masz repozytorium Github dla tego kodu?
ipolevoy,
@ipolevoy Jak sobie życzyłeś, dodałem go do GitHub .
Victor Stafusa,
doceniam wysiłek!
ipolevoy,
16

Freepascal

Ten zegar wyświetla godzinę, datę i fazę księżyca. Jednak w przeciwieństwie do zegarów mechanicznych, które mają małe okno do wyświetlania fazy księżyca, w moim zegarze wyświetlana jest cała twarz. Dzisiaj 14 lutego jest pełnią księżyca. Poniżej możesz zobaczyć oczekiwany wynik w ciągu najbliższych kilku dni.

uses graph,sysutils;

const hemisphere=-1; {-1=north,1=south}
MonthStr : array[1..12] of string [3] =
('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep ','Oct','Nov','Dec');

var yy,dd,mm,hh,mn,ss,ms: word;
var s: string; d2fullmoon,hour,min:real; sec:word;

var gd, gm, n : integer;
var right, left, centre: word;

begin

  gd := D4bit;
  gm := m640x480;
  initgraph(gd,gm,'');
  setbkcolor(blue);cleardevice; setbkcolor(black);
  setlinestyle(0,0,3);
  settextjustify(centertext,centertext);
  settextstyle(defaultfont,horizdir,2);

  while true do begin

    {output to console}

    DecodeDate(Date,YY,MM,DD);
    Writeln (Format ('Today is %d/%d/%d',[dd,mm,yy]));

    DecodeTime(Time,HH,Mn,SS,MS);
    Writeln (format('The time is %d:%d:%d.%d',[hh,mm,ss,ms]));

    d2fullmoon:=yy*(365*3+366)/4+mm*365/12+dd-2014*(365*3+366)/4-2*365/12-14;
    writeln ('days since full moon 14 feb 2014 ',d2fullmoon);

    if ss mod 15=0 then begin {Refresh display every 15 sec. Only the second hand is refreshed every sec.}

      {Draw circle and 180deg pie in yellow/black. Draw yellow or black ellipse on top. Add boxes for date}

      if sin(d2fullmoon/29.530588853*2*pi)*hemisphere>0 then right:=yellow else right:=black;
      left:=yellow-right;

      setcolor(right);setfillstyle(solidfill,right);
      fillellipse(320,240,200,200);

      setfillstyle(solidfill,left);setcolor(left);
      pieslice(320,240,90,270,200);

      if cos(d2fullmoon/29.530588853*2*pi)>0 then centre:=yellow else centre:=black;
      setcolor(centre); setfillstyle(solidfill,centre);
      fillellipse(320,240,abs(trunc(200*cos(d2fullmoon/29.530588853*2*pi))),200);

      setcolor (blue); setfillstyle(solidfill,blue);
      bar (270,135,370,165); bar (270,345,370,315);

      {fill in numbers}

      for n:=1 to 12 do begin
        setcolor(blue); setfillstyle(solidfill,blue);
        fillellipse(319+trunc(170*sin(n*pi/6)),240-trunc(170*cos(n*pi/6)),15,15);
        fillellipse(320+trunc(170*sin(n*pi/6)),240-trunc(170*cos(n*pi/6)),15,15);

        moveto(322+trunc(170*sin(n*pi/6)),240-trunc(170*cos(n*pi/6)));
        setcolor(white);
        str(n,s);outtext(s);
      end;

      {fill in date}

      str(yy,s);
      moveto(320,330);outtext(s);
      str(dd,s);
      moveto(320,150);outtext(s+monthstr[mm]);

      {draw hour and minute hands}

      hour:=hh+mn/60; min:=mn+ss/60;
      setcolor(cyan) ;setfillstyle(solidfill,cyan);
      moveto(320,240);
      linerel(trunc(140*sin(min*pi/30)),trunc(-140*cos(min*pi/30)));
      fillellipse(320+trunc(140*sin(min*pi/30)),240+trunc(-140*cos(min*pi/30)),7,7);
      moveto(320,240);
      linerel(trunc(100*sin(hour*pi/6)),trunc(-100*cos(hour*pi/6)));
      fillellipse(320+trunc(100*sin(hour*pi/6)),240+trunc(-100*cos(hour*pi/6)),7,7);
      fillellipse(320,240,10,10);

    end;

    {draw second hand in XOR mode, sleep for a second, then repeat to undraw}

    sec:=ss;
    setwritemode(xorput); setcolor(white);
    moveto(320+trunc(12*sin(sec*pi/30)),240+trunc(-12*cos(sec*pi/30)));
    linerel(trunc(150*sin(sec*pi/30)),trunc(-150*cos(sec*pi/30)));

    Sleep(1000);

    moveto(320+trunc(12*sin(sec*pi/30)),240+trunc(-12*cos(sec*pi/30)));
    linerel(trunc(150*sin(sec*pi/30)),trunc(-150*cos(sec*pi/30)));
    setwritemode(copyput);

  end;
  closegraph;
end.

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

Level River St
źródło
Cudownie, bardzo mi się podobał.
Victor Stafusa
12

Prosty mój przyjaciel napisał w TI 84 BASIC:

StoreGDB 0
CoordOff
GridOff
AxesOff
LabelOff
ExprOff
ClrDraw
62->Ymax
0->Ymin
94->Xmax
0->Xmin
Func
FnOff 0,1,2,3,4,5,6,7,8,9
PlotsOff 1,2,3
Full
Xmax/2->Xmax
Ymax/2->Ymax
~Xmax->Xmin
~Ymax->Ymin
Degree

15->H
18->M
20->S

Circle(36,~22,7)
Circle(0,0,30)
For(X,1,12)
Text(28-int(cos(X*30)*25),46+int(sin(30*X)*25),X)
End

{0,0,0}->|LANG

While getKey=0
getTime->|LTIME
getDate->|LDATE

Text(0,0,"12 HR")
Text(50,0,"24 HR")
If |LTIME(1)>12:Then
Text(6,7,(|LTIME(1)-12))
Else
Text(6,7,|LTIME(1))
End

If |LTIME(1)<=9
Then
Text(56,4,"O")
Text(56,8,|LTIME(1))
Else
Text(56,4,|LTIME(1))
End

Text(29,4,|LTIME(2))


If |LDATE(2)=1
Text(0,70,"JAN")

If |LDATE(2)=2
Text(0,70,"FEB")

If |LDATE(2)=3
Text(0,70,"MAR")

If |LDATE(2)=4
Text(0,70,"APR")

If |LDATE(2)=5
Text(0,70,"MAY")

If |LDATE(2)=6
Text(0,70,"JUN")

If |LDATE(2)=7
Text(0,70,"JUL")

If |LDATE(2)=8
Text(0,70,"AUG")

If |LDATE(2)=9
Text(0,70,"SEP")

If |LDATE(2)=10
Text(0,70,"OCT")

If |LDATE(2)=11
Text(0,70,"NOV")

If |LDATE(2)=12
Text(0,70,"DEC"
Text(2,81,",")
Text(0,85,|LDATE(3))
Text(8,75,|LDATE(1))


If |LTIME(1)>=12
Then
Text(50,80,"PM")
Else
Text(50,80,"AM")
End

If |LTIME(3)!=|LANG(3)/6
Line(0,0,sin(|LANG(3))*S,cos(|LANG(3))*S,0)

If |LTIME(2)!=|LANG(2)/6
Then
Line(0,0,sin(|LANG(2))*M,cos(|LANG(2))*M,0)
Line(0,0,sin(|LANG(1))*H,cos(|LANG(1))*H,0)
End

|LTIME(1)*30+|LTIME(2)/2->|LANG(1)
|LTIME(2)*6->|LANG(2)
|LTIME(3)*6->|LANG(3)

Line(0,0,sin(|LANG(1))*H,cos(|LANG(1))*H
Line(0,0,sin(|LANG(2))*M,cos(|LANG(2))*M
Line(0,0,sin(|LANG(3))*S,cos(|LANG(3))*S
End

wprowadź opis zdjęcia tutaj

Doktor
źródło
Dałbym to +100, gdybym mógł :)
Timtech
Czy możesz opublikować zrzut ekranu?
Victor Stafusa
nie, mój TI-84 jest zepsuty i nie mogę znaleźć dobrego emulatora
TheDoctor
2
@Victor - dostałem w ręce TI, aktualizując w / zrzut ekranu
TheDoctor
@TheDoctor Nice. :)
Victor Stafusa
9

Matematyka

Zwykły waniliowy, działający zegar, który wyświetla czas lokalny:

Dynamic@Refresh[ClockGauge@AbsoluteTime[], UpdateInterval -> 1]

zegar


Opcje standardowe

opcje


Ręcznie rysowane zegar zegarowy

Istnieją alternatywy dla wbudowanego zegara. Tutaj jest jeden.

Ciągłe przemiatanie zostało wdrożone dla wskazówek godzin i minut. Aktualizują się wraz z drugą ręką.

u[i_, k_] := {Sin[2 \[Pi] i/k], Cos[2 \[Pi] i/k]};
Dynamic[{f = Date[], Clock[{1, 1}, 1]}]
Graphics[Dynamic@{Circle[{0, 0}, 1.175], Circle[{0, 0}, 1.2],

   (* tick marks at minutes *)
   Table[Text[".", u[i, 60]], {i, 60}],  

   (* hour labels *)
   Table[Text[i, u[i, 12]], {i, 12}],  

   (* hour hand *)
   {Darker@Red, Arrowheads[.12], Thickness[.0175], Arrow[{{0, 0}, .6 u[f[[4]]+f[[5]]/60, 12]}]},

   (*minute hand *)
   {Blue, Arrowheads[.08], Thickness[.0085], Arrow[{{0, 0}, .85 u[f[[5]]+f[[6]]/60, 60]}]},

   (*second hand *)
   {Thickness[.005], Arrow[{{0, 0}, .9 u[f[[6]], 60]}]}}, 
   BaseStyle -> 25]

zegar 4

DavidC
źródło
Osierociłeś linię kodu u góry ręcznie rysowanego bloku kodu miernika. Edytowałbym to, ale system nie pozwala na edycję jednoznakową, a wszystko, czego potrzebuje, to nowa linia.
Jonathan Van Matre
8

Postscript - pierwotnie napisany, aby pomóc moim dzieciom nauczyć się mówić godzinę. Strona 1 pokazuje aktualny czas, strony 2-4 to strony dla uczniów. Strony dla uczących się służą randdo tworzenia losowych czasów, więc są różne przy każdym przetwarzaniu. Użyj Ghostscript, aby utworzyć wersję PDF, jeśli chcesz pokazać aktualny czas. Rozmiar papieru A4.

%!PS-Adobe-3.0
%%Creator: Toby Thurston
%%Title: (Pages of pedagogical clocks)
%%CreationDate: (2014-02-14)
%%BoundingBox: 12 12 583 828 
%%Pages: 1
%%EndComments
<< /PageSize [595 842] >> setpagedevice
%%BeginSetup
/clock {
  /mins exch def
  /hour exch def
  /r exch def % radius
  /cr r 100 div def
  % draw the minute marks
  12 { .5 setlinewidth 4 { 6 rotate r 0 moveto r 20 div 0 rlineto stroke } repeat
        2 setlinewidth     6 rotate r 0 moveto r 20 div 0 rlineto stroke } repeat  
  % numbers           
  /fontsize r 0.14 mul def
  /Helvetica findfont fontsize scalefont setfont
  /s 2 string def 
  /rr r 0.9 mul def
  1 1 12 { /n exch def /theta 90 30 n mul sub def
  /st n s cvs def st stringwidth pop /dx exch 2 div neg def
  rr theta cos mul rr theta sin mul moveto dx fontsize 3 div neg rmoveto st show
  } for

  % draw hands (unless hour is negative)
  -1 hour lt {
      gsave % hour hand first
      90 60 hour mul mins add 2 div sub rotate
      newpath
      0 2 moveto
      15 cr mul  3 cr mul 33 cr mul   0 cr mul 50 cr mul  3 cr mul curveto 
      55 cr mul 15 cr mul 60 cr mul   0 cr mul 76 cr mul  0 cr mul curveto
      60 cr mul  0 cr mul 55 cr mul -15 cr mul 50 cr mul -3 cr mul curveto 
      33 cr mul  0 cr mul 15 cr mul  -3 cr mul  0 cr mul -2 cr mul curveto
      closepath 0 0 .677 setrgbcolor fill
      grestore
      gsave % minute hand on top
      90 6 mins mul sub rotate
      newpath
      0 2 moveto
      15 cr mul 3 cr mul 33 cr mul 0         50 cr mul  1 cr mul curveto 
      65 cr mul 3 cr mul 83 cr mul 0         97 cr mul  0        curveto
      83 cr mul 0        65 cr mul -3 cr mul 50 cr mul -1 cr mul curveto 
      33 cr mul 0        15 cr mul -3 cr mul 0         -2 cr mul curveto
      closepath .635 0 0 setrgbcolor fill
      grestore
  } if 

  % finally do central dot (to cover starts of hands) and outer band      
  .5 setlinewidth
  0 0 moveto 0 0 r 20 div   0 360 arc fill
             0 0 r 1.07 mul 0 360 arc stroke

} def
%%EndSetup
%%Page: 1 1 
%%BeginPageSetup
/pgsave save def
%%EndPageSetup
  297 480 translate
  120 

  (%Calendar%) /IODevice resourcestatus {
   pop pop (%Calendar%) currentdevparams
   dup /Running get { dup /Hour get exch /Minute get }{ 0 0 } ifelse } { -1 -1 } ifelse

  clock
pgsave restore
showpage
%%Page: 2 2
%%BeginPageSetup
/pgsave save def
%%EndPageSetup
  75 -55 translate
  4 {
     5 { 0 165 translate % a page of clocks for learners
         50 rand 12 mod rand 60 mod clock 
         % line underneath           
         gsave [1 3] 0 setdash 50 neg dup 1.8 mul moveto 50 2 mul 0 rlineto stroke grestore
     } repeat
     146 5 165 mul neg translate
  } repeat
pgsave restore
showpage
%%Page: 3 3
%%BeginPageSetup
/pgsave save def
%%EndPageSetup
  75 -55 translate
  4 {
     5 { 0 165 translate    % whole multiple of five minutes only
         50 rand 12 mod rand 12 mod 5 mul clock 
         gsave [1 3] 0 setdash 50 neg dup 1.8 mul moveto 50 2 mul 0 rlineto stroke grestore
     } repeat
     146 5 165 mul neg translate
  } repeat
pgsave restore
showpage
%%Page: 4 4
%%BeginPageSetup
/pgsave save def
%%EndPageSetup
  75 -55 translate
  4 {
     5 { 0 165 translate    % quarter hours only
         50 rand 12 mod rand 4 mod 15 mul clock 
         gsave [1 3] 0 setdash 50 neg dup 1.8 mul moveto 50 2 mul 0 rlineto stroke grestore
     } repeat
     146 5 165 mul neg translate
  } repeat
pgsave restore
showpage
%%EOF

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

Truston
źródło
4
+1 za napisanie Postscriptum, aby nauczyć swoje dzieci. Jesteś niesamowitym rodzicem.
Jonathan Van Matre
Czy randza każdym razem nie dasz takich samych wyników? Chyba że jakoś go zasiejesz (/dev/rand)(r)file read pop srand.
luser droog
@luserdroog ... err no. Potrzebujesz tylko, srandjeśli chcesz ustalić swoją pozycję w sekwencji liczb pseudolosowych PS. Cytując PSLRM: „Wykonanie srandz określoną wartością powoduje kolejne wywołania w randcelu wygenerowania powtarzalnej sekwencji wyników”.
Thruston
Zgadza się, ale sam interpreter inicjuje się 1 srandprzed uruchomieniem programów użytkownika. Musisz więc wprowadzić własną entropię, aby uzyskać niepowtarzalną sekwencję. Nie testowałem z Distillerem, ale to właśnie robi Ghostscript. gsnd -q -dBATCH -c 'rand ='zawsze daje mi 16807.
luser droog
4

Demo: http://jsfiddle.net/kelunik/Vuuq8/7/embedded/result/

HTML

<div id="clock">
    <div id="h"></div>
    <div id="m"></div>
    <div id="s"></div>
</div>

CSS

html, body {
    margin: 0;
    padding: 0;
    text-align: center;
}
#clock {
    width: 100vmin;
    height: 100vmin;
    border-radius: 50%;
    border: 1vmin solid #333;
    position: relative;
    box-shadow: 0 0 5vmin rgba(0, 0, 0, .3);
    box-sizing: border-box;
    margin: 0 auto;
    transform: scale(.8);
}
#h, #m, #s {
    top: 50vmin;
    left: 50vmin;
    position: absolute;
}
#h:before, #m:before, #s:before {
    content:"";
    position: absolute;
    left: 100%;
    height: 0;
    box-shadow: 0 0 2vmin rgba(0,0,0,.2);
    border-radius: 50%;
}
#h:before {
    width: 25vmin;
}
#m:before {
    width: 35vmin;
}
#s:before {
    width: 45vmin;
}
#h:before {
    background: black;
    height: 4vmin;
    transform: translateY(-2vmin);
}
#m:before {
    background: black;
    height: 2vmin;
    transform: translateY(-1vmin);
}
#s:before {
    background: red;
    height: 2vmin;
    transform: translateY(-1vmin);
}

JavaScript

var h = document.getElementById('h');
var m = document.getElementById('m');
var s = document.getElementById('s');

setInterval(function () {
    refreshClock();
}, 1000);

function refreshClock() {
    var time = new Date;

    deg = time.getSeconds() * 6 - 90;
    s.style.webkitTransform = s.style.MozTransform = s.style.msTransform = s.style.transform = "rotate(" + deg + "deg)";

    deg = time.getMinutes() * 6 - 90;
    m.style.webkitTransform = m.style.MozTransform = m.style.msTransform = m.style.transform = "rotate(" + deg + "deg)";

    deg = time.getHours() % 12 * 30 - 90;
    h.style.webkitTransform = h.style.MozTransform = h.style.msTransform = h.style.transform = "rotate(" + deg + "deg)";
}

window.onload = function () {
    refreshClock();
};
kelunik
źródło
Dostaję zegar, ale wskazówki godzin i minut (i sekund?) Są skierowane prosto w prawo. Nic się nie rusza.
Justin
Jakiej przeglądarki używasz?
kelunik
Google Chrome ..
Justin
Twoja odpowiedź wygląda obiecująco i interesująco, ale teraz zawodzi. Coś jest nie tak z właściwością transformacji CSS w funkcji refreshClock (ale nie wiem dokładnie co). Próbowałem tego w IE, chrome i firefox, nie działało w nikim.
Victor Stafusa,
@Victor Wygląda na to, że działa teraz tylko w Firefoksie, ale tam działa.
kelunik
4

Oto jeden w przetwarzaniu:

int ax,ay,bx,by,cx,cy,dx,dy,last;
int q = 1;
float c = 0;
float h = 0;
float m = 0;

void setup() {
  size(displayWidth, displayHeight);
  background(0);
}

boolean sketchFullScreen() {
  return true;
}

void draw() {
  colorMode(HSB);
  fill(c,255,255,4);
  noStroke();
  rect(0,0,width,height);

  c+=0.4;
  if (c > 255) c = 0;

  colorMode(RGB);

  ax = int(random(displayWidth));
  ay = int(random(displayHeight));
  bx = ax + int(random(-50,50));
  by = ay + int(random(0,50));

  strokeWeight(1);

  if (random(0,1)>0.5) {
    fill(random(255),random(255),random(255));
    stroke(random(255),random(255),random(255));
  }
  else {
    noFill();
    stroke(random(255),random(255),random(255));
  }

  switch(int(random(6))) {
    case 0: // line
    line(ax,ay,bx,by);

    break;
    case 1: // bezier (arc)
    cx = int(random(ax-20,bx+20));
    cy = int(random(ay-20,by+20));
    dx = int(random(ax-20,bx+20));
    dy = int(random(ay-20,by+20));
    bezier(ax,ay,cx,cy,dx,dy,bx,by);

    break;
    case 2: // box
    quad(ax,ay,ax,by,bx,by,bx,ay);

    break;
    case 3: // ellipse
    ellipse(ax,ay,random(15,50),random(15,50));

    break;
    case 4: // triangle
    cx = int(random(ax-20,bx+20));
    cy = int(random(ay-20,by+20));
    dx = int(random(ax-20,bx+20));
    dy = int(random(ay-20,by+20));
    triangle(cx,cy,bx,by,dx,dy);

    break;
    case 5: // arc
    arc(ax,ay,random(15,50),random(15,50),random(2)*PI,random(2)*PI);

    break;  
  }

  float s = map(second(), 0, 60, 0, TWO_PI) - HALF_PI;
  float m = map(minute() + norm(second(), 0, 60), 0, 60, 0, TWO_PI) - HALF_PI; 
  float h = map(hour() + norm(minute(), 0, 60), 0, 24, 0, TWO_PI * 2) - HALF_PI;

  cx = width/2;
  cy = height/2;

  // Draw the hands of the clock
  stroke(255);
  strokeWeight(1);
  line(cx, cy, cx + cos(s) * 500, cy + sin(s) * 500);
  strokeWeight(2);
  line(cx, cy, cx + cos(m) * 400, cy + sin(m) * 400);
  strokeWeight(4);
  line(cx, cy, cx + cos(h) * 300, cy + sin(h) * 300);

}

void mouseMoved() {
  exit();
}
void keyPressed() {
  background(0);
}

to pełny ekran

Doktor
źródło
To jest takie piękne!
danmcardle
Mówi, że nie mogę przesłonić metody z PApplet?
Kritixi Lithos
@danmcardle: To takie brzydkie!
sergiol
3

GNUPLOT

unset clip points
set clip one
unset clip two
set bar 1.000000
unset border
set xdata
set ydata
set zdata
set x2data
set y2data
set timefmt x "%d/%m/%y,%H:%M"
set timefmt y "%d/%m/%y,%H:%M"
set timefmt z "%d/%m/%y,%H:%M"
set timefmt x2 "%d/%m/%y,%H:%M"
set timefmt y2 "%d/%m/%y,%H:%M"
set timefmt cb "%d/%m/%y,%H:%M"
set boxwidth
set style fill  empty border
set dummy t,y
set format x "% g"
set format y "% g"
set format x2 "% g"
set format y2 "% g"
set format z "% g"
set format cb "% g"
set angles radians
unset grid
set key title ""
unset key
unset label
unset arrow
unset style line
unset style arrow
set style histogram clustered gap 2 title  offset 0, 0, 0
unset logscale
set offsets 0, 0, 0, 0
set pointsize 1
set encoding default
unset polar
set parametric
unset decimalsign
set view 60, 30, 1, 1
set samples 100, 100
set isosamples 10, 10
set surface
unset contour
set clabel '%8.3g'
set mapping cartesian
set datafile separator whitespace
unset hidden3d
set cntrparam order 4
set cntrparam linear
set cntrparam levels auto 5
set cntrparam points 5
set size ratio 0 1,1
set origin 0,0
set style data points
set style function lines
set xzeroaxis linetype -2 linewidth 1.000
set yzeroaxis linetype -2 linewidth 1.000
set zzeroaxis linetype -2 linewidth 1.000
set x2zeroaxis linetype -2 linewidth 1.000
set y2zeroaxis linetype -2 linewidth 1.000
set ticslevel 0.5
set mxtics default
set mytics default
set mztics default
set mx2tics default
set my2tics default
set mcbtics default
set noxtics
set noytics
set noztics
set nox2tics
set noy2tics
set nocbtics
set title ""  offset character 0, 0, 0 font "" norotate
set timestamp bottom 
set timestamp ""  offset character 0, 0, 0 font "" norotate
set rrange [ * : * ] noreverse nowriteback  # (currently [0.000000:10.0000] )
set trange [ * : * ] noreverse nowriteback  # (currently [-5.00000:5.00000] )
set urange [ * : * ] noreverse nowriteback  # (currently [-5.00000:5.00000] )
set vrange [ * : * ] noreverse nowriteback  # (currently [-5.00000:5.00000] )
set xlabel ""  offset character 0, 0, 0 font "" textcolor lt -1 norotate
set x2label ""  offset character 0, 0, 0 font "" textcolor lt -1 norotate
set xrange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
set x2range [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
set ylabel ""  offset character 0, 0, 0 font "" textcolor lt -1 rotate by 90
set y2label ""  offset character 0, 0, 0 font "" textcolor lt -1 rotate by 90
set yrange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
set y2range [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
set zlabel ""  offset character 0, 0, 0 font "" textcolor lt -1 norotate
set zrange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
set cblabel ""  offset character 0, 0, 0 font "" textcolor lt -1 norotate
set cbrange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
set zero 1e-008
set lmargin -1
set bmargin -1
set rmargin -1
set tmargin -1
set locale "C"
set pm3d explicit at s
set pm3d scansautomatic
set pm3d interpolate 1,1 flush begin noftriangles nohidden3d corners2color mean
set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB 
set palette rgbformulae 7, 5, 15
set colorbox default
set colorbox vertical origin screen 0.9, 0.2, 0 size screen 0.05, 0.6, 0 bdefault
set loadpath 
set fontpath 
set fit noerrorvariables
set arrow from 0,0 to sin(`date +%M`*3.1416/30),cos(`date +%M`*3.1416/30) 
set arrow from 0,0 to sin((`date +%H`%12)*3.1416/6)/2,cos((`date +%H`%12)*3.1416/6)/2
plot sin(t),cos(t)
reread

w linux centos 6.5

delfosse
źródło
+1 Działa nawet w oknie Tektronix. xterm -t -e "gnuplot -e 'set term tek40xx' clock.plot"(z irytującymi mrugnięciami)
luser droog
1
Aby uniknąć mrugnięć, możesz dodać „pauzę 60” tuż przed ponownym odczytaniem
delfosse
3

Prosty kod MATLAB, pisany głównie z myślą o 24-godzinnym wybieraniu w pracy.

Przykład zegarka MATLAB z tarczami 24-godzinnymi i 12-godzinnymi podczas gdy 1 runWatch () pauza (0.6); koniec

% 20160829 :: [email protected]
function runWatch()
cla;

dialHours  = 24;   % You can set it to 12 but why?
midnightUp = true; % defines position of midnight

col.hr = 'k'; 
col.mn = 'b'; 
col.sc = 'r'; 

logoStr = ['Perpetuum'];

xo = 0; yo = 0; 
RH  = 0.7;   RM  = 0.95; Rb = 0.5*(RH+RM);
RarrH = RH; RarrM = Rb; RarrS = RM;

fig_handle = findobj(allchild(0), 'flat', 'type', 'figure');

if isempty(fig_handle), set(gcf,'Position',[100 100 500 500]); end
hoursPhase = 3*pi/2; if midnightUp == true, hoursPhase = pi/2; end

hold on;
circle(xo, yo, RH,col.hr); 
circle(xo, yo, RM,col.mn);% ,'b');
circle(xo, yo, (RH+RM)/2,col.mn); %0.5*[1 1 1]);

text (xo - 2.5*RH/8+0.003, yo - RH/2-0.003, logoStr,'Color',0.5*[1 1 1],'FontAngle','italic');
text (xo - 2.5*RH/8,       yo - RH/2,       logoStr, 'FontAngle','italic')
axis equal; axis off;

% Hour dial
dh = pi/dialHours; h = 0:-dh:-pi+dh;
xH = RH*cos(2*h+hoursPhase); yH = RH*sin(2*h+hoursPhase);
xHb= Rb*cos(2*h+hoursPhase); yHb= Rb*sin(2*h+hoursPhase);
for n=1:length(xH)
    plot([xH(n),xHb(n)],[yH(n),yHb(n)],col.hr);
end
% Minute dial
dm = pi/60; m = 0:-dm:-pi+dm;
xM = RM*cos(2*m+pi/2); yM = RM*sin(2*m+pi/2);
xMb= Rb*cos(2*m+pi/2); yMb= Rb*sin(2*m+pi/2);
for n=1:length(xM)
    plot([xM(n),xMb(n)],[yM(n),yMb(n)],'Color',col.mn);
end

% Labels Hour
dhl = pi/dialHours; hl = 0:-dhl:-pi+dhl;  ratioH = -dialHours/180;
xHl= 0.5*(Rb+RH)*cos(2*hl+hoursPhase); 
yHl= 0.5*(Rb+RH)*sin(2*hl+hoursPhase);
for n=1:length(xHl)
    octagon (xHl(n), yHl(n), 0.3*(RH-Rb), 'w');
    text (xHl(n),yHl(n), num2str( rad2deg(hl(n)*ratioH) ),...
        'HorizontalAlignment','center','Rotation',rad2deg(2*hl(n)+hoursPhase-pi/2),...
        'FontWeight','b','FontSize',13,'Color',col.hr);    

end

% Labels Minute
dml = pi/12; ml=0:-dml:-pi+dml;  ratioM = -60/180; 
xMl= 0.5*(Rb+RM)*cos(2*ml+pi/2); yMl= 0.5*(Rb+RM)*sin(2*ml+pi/2);
for n=1:length(xMl)    
    octagon (xMl(n), yMl(n), 0.3*(RM-Rb), 'w');
    text (xMl(n),yMl(n), num2str( rad2deg(ml(n)*ratioM) ),...
        'HorizontalAlignment','center','Rotation',rad2deg(2*ml(n)), ...
        'FontWeight','b','Color',col.mn);
end

octagon (xo, yo-0.5*(RH+Rb), 0.04, col.hr);
octagon (xo, yo-0.5*(RH+Rb), 0.03, col.mn);

[now_year, now_month, now_day, ...
    now_hour, now_minute, now_second] = datevec(now);

% Arrows
K = -2*pi/dialHours; D = hoursPhase;
now_hour = now_hour + now_minute/60;
xarrowh = RarrH*cos(K*now_hour+D);
yarrowh = RarrH*sin(K*now_hour+D);
plot([0,xarrowh],[0,yarrowh],'Color',col.hr,'LineWidth',6); 
plot([0,xarrowh],[0,yarrowh],'Color',0.5*[1 1 1],'LineWidth',3); 
arrowhead (xarrowh,yarrowh,0.02,atan2(yarrowh,xarrowh),col.hr);

K = -2*pi/60; D = pi/2;
now_minute = now_minute + now_second/60;
xarrowm  = RarrH*cos(K*now_minute+D);
yarrowm  = RarrH*sin(K*now_minute+D);
xarrowml = RarrM*cos(K*now_minute+D);
yarrowml = RarrM*sin(K*now_minute+D);
plot([0,xarrowml],[0,yarrowml],'Color','k', 'LineWidth',4);
plot([0,xarrowml],[0,yarrowml],'Color',col.mn, 'LineWidth',2);
arrowhead (xarrowml,yarrowml,0.02,atan2(yarrowml,xarrowml),col.mn);

K = -2*pi/60; D = pi/2;
now_second = round(now_second);
xarrows = RarrH*cos(K*now_second+D);
yarrows = RarrH*sin(K*now_second+D);
xarrowsl = RarrS*cos(K*now_second+D);
yarrowsl = RarrS*sin(K*now_second+D);
plot([0,xarrowsl],[0,yarrowsl],'Color',col.sc,'LineWidth',1);
arrowhead (xarrowsl,yarrowsl,0.02,atan2(yarrows,xarrows)-pi,col.sc);

text(0.7,1,...
    [pad_with(floor(now_hour),2,'0'), ':', pad_with(floor(now_minute),2,'0'), ':', pad_with(now_second,2,'0')],...
    'FontSize',8,'FontWeight','n','BackgroundColor','w');

% Dial center
plot(xo, yo, 'ko','MarkerSize',10,'MarkerFaceColor','k');
plot(xo, yo, 'ko','MarkerSize',8,'MarkerFaceColor',0.5*[0 1 1]);

end

function [XX,YY] = circle(varargin)
%x and y are the coordinates of the center of the circle
%r is the radius of the circle
%0.01 is the angle step, bigger values will draw the circle faster but
%you might notice imperfections (not very smooth)

col = 'k';
x = varargin{1};
y = varargin{2};
r = varargin{3};
if length(varargin) > 3
    col = varargin{4};
end

ang=0:0.01:2*pi; 
xp=r*cos(ang);
yp=r*sin(ang);
XX = x+xp; YY = y+yp;
plot(XX,YY,'Color',col);
end

function octagon (xo, yo, R, col)

t = (1/16:1/8:1)'*2*pi;
x = R*cos(t);
y = R*sin(t);
fill(xo+x, yo+y,col,'EdgeColor','none')
end

% 20151001 :: [email protected]
% Use :: str = pad_with (num, L, pad)
% function creates a string of L length
% padded with leading 'pad' symbol
% e.g., num=23,    L=4, pad='.' --> '..23';
% e.g., num='23W', L=4, pad=' ' --> ' 23W';
% 
function str = pad_with (num, L, pad)

if ~ischar(num)
    num = num2str(num);
end
strL = length(num);
if L<strL, L = strL; end;
for n=1:L-strL, str(n) = pad; end;
c = 0;
for n=L-strL+1:L
    c = c+1; str(n) = num(c);
end
end

function [x, y] = arrowhead (xo, yo, height, alpha, col)

x(1) = xo + height*sin(alpha);
y(1) = yo - height*cos(alpha);

x(2) = xo - height*sin(alpha);
y(2) = yo + height*cos(alpha);

x(3) = xo + 2*height*cos(alpha);
y(3) = yo + 2*height*sin(alpha);

fill(x, y,col,'EdgeColor','none')
end
winogrona
źródło
1
Witamy w PPCG! Ładna pierwsza odpowiedź.
FantaC
2

Python (z matplotlib)

Oto bardzo prosty zegar, który działa na pulpicie. Zmień intervalod drugiej do ostatniej linii 1na ciągły ruch zamiast jednego tiku na sekundę.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import datetime

plt.rcParams['toolbar'] = 'None' 
fig = plt.figure(figsize=(4,4),facecolor='w')
ax = plt.subplot(111, polar=True)
plt.axes().get_yaxis().set_visible(False)

#12 labels, clockwise
marks = np.linspace(360./12,360,12, endpoint=True)
ax.set_thetagrids(marks,map(lambda m: int(m/30),marks),frac=.85,size='x-large')
ax.set_theta_direction(-1)
ax.set_theta_offset(np.pi/2)
ax.grid(None)

#hands
wids  = [.2,.03,.01]
lens  = [.75,.9,1]
clrs = plt.cm.winter(np.linspace(0, 1, 3))
factor = [12,60,60,1]

#convert time to radians
def timedata():
    x =  str(datetime.datetime.now().time())
    fig.canvas.set_window_title(x[:8])
    data = map(lambda n: float(n), x.split(':'))+[0]
    for i in range(3):
        data[i]=2*np.pi*(data[i]/factor[i]+data[i+1]/factor[i+1]/factor[i])
        data[i]-=(wids[i]/2)
    return data[:3]

#create hands
bars = ax.bar(timedata(), lens, width=wids, bottom=0.0, color=clrs, linewidth=0)
map(lambda b: b.set_alpha(0.5), bars)

#tick
def animate(i):
    map(lambda bt: bt[0].set_x(bt[1]), zip(bars,timedata()))
    return bars

ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), interval=1000)
plt.show()

pyclock

AShelly
źródło
2

Matematyka

Używam więcej kodu demonstracyjnego z przeglądarki pomocy Mathematica, niż powinienem

zegar

z

Voltmeter3[v_, label_] := 
  Graphics[{{(*case*){EdgeForm[{Thickness[.007], GrayLevel[0]}], 
      GrayLevel[.2], 
      Rectangle[{-1.2, -1.1}, {1.2, 1.3}, 
       RoundingRadius -> .2]},(*case holes*){White, 
      Disk[{-1, -.9}, .05], Disk[{1, -.9}, .05], Disk[{1, 1.1}, .05], 
      Disk[{-1, 1.1}, .05]},(*case outer rim*){Black, 
      Disk[{0, .1}, 1.15], GrayLevel[.5], Disk[{-.02, .12}, 1.13], 
      GrayLevel[.2], Disk[{0, .1}, 1.11]},(*face highlight*)
     EdgeForm[{CapForm["Round"], Thickness[.02], Hue[.125, .7, .6]}], 
     Hue[.125, 1, 1], 
     Disk[{.02, .1}, 
      1, {1.1 Pi, -.1 Pi}],(*face shadow*){EdgeForm[{CapForm["Round"],
         Thickness[.01], Hue[.125, 1, 1]}], Hue[.125, 1, 1], 
      Disk[{-.02, .12}, 1, {1.1 Pi, -.1 Pi}]},(*face*){EdgeForm[], 
      Hue[.125, .5, 1], 
      Rotate[Polygon[({.1, -.04} + # &) /@ 
         Flatten[{{{0, 0}, {0, 1}}, 
           Array[{Sin[2 Pi*(#/50)], Cos[2 Pi*(#/50)]} &, 30]}, 1], 
        VertexColors -> 
         Flatten[{Hue[.125, 0, 1], 
           Array[Hue[.125, .5, 1] &, 50 + 1]}]], 
       30/50 Pi, {0, 
        0}]},(*case mid line highlight*){Hue[.125, .7, .6], 
      Thickness[.025], CapForm["Round"], 
      Line[{{-.95, -.2}, {0, .1}, {.95, -.2}}]},(*case mid disk \
highlight*){Hue[.125, .7, .6], Disk[{0, 0}, .25, {.95 Pi, .05 Pi}]}},
    Inset[
     AngularGauge[v, {0, 100}, GaugeFaceStyle -> None, 
      GaugeFrameStyle -> None, 
      GaugeMarkers -> 
       Graphics[{Hue[0, 1, .7], 
         Polygon[{{.1, .03}, {.1, -.03}, {.95, -.03}, {1, 
            0}, {.95, .03}}]}], 
      GaugeLabels -> {Placed[
         Style[label, FontFamily -> "Helvetica", Bold, 
          FontSize -> Scaled[.08], White], {.5, .35}]}, 
      LabelStyle -> 
       Directive[FontFamily -> "Helvetica", FontSize -> Scaled[.06]], 
      ScaleOrigin -> {{.85 Pi, .15 Pi}, .9}, 
      ScaleDivisions -> {2, 10}, 
      ScaleRanges -> {{Scaled[.75], Scaled[1]}}, 
      ScaleRangeStyle -> Hue[0, 1, .7, .7], AxesStyle -> Opacity[0], 
      TicksStyle -> {Thickness[.01], Thickness[.005]}, 
      ImageSize -> Automatic, ImagePadding -> None], {0, 0}, {0, 
      0}, {1.75, Automatic}], {(*case mid disk*)GrayLevel[.2], 
     Disk[{0, 0}, .2], GrayLevel[0], Disk[{0, 0}, .075], 
     Disk[{-.85, -.4}, .05], Disk[{.85, -.4}, .05]}}, 
   PlotRangeClipping -> True];

Dynamic@Refresh[
  GraphicsRow[{Voltmeter3[DateList[][[4]], "Hour"], 
    Voltmeter3[DateList[][[5]], "Minute"], 
    Voltmeter3[DateList[][[6]], "Second"]}], UpdateInterval -> 1]
Michael Stern
źródło
1

C + Kair + xcb

Zasadniczo oderwałem rozwiązanie PostScript i przetłumaczono na Kair. :)

Niektórzy muszą to robić: ps używa stopni, Kair używa radianów; ps orientuje okno za pomocą + y w górę , xcb orientuje je za pomocą + y w dół .

//xclock.c
//cc $(pkg-config --cflags --libs cairo xcb xcb-icccm) -o xclock xclock.c -lcairo -lxcb -lxcb-icccm
#include <math.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <cairo.h>
#include <cairo-xcb.h>
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_icccm.h>

double deg_rad (double rad){
    return rad * (180.0/M_PI);
}

double rad_deg (double deg){
    return deg * (M_PI/180.0);
}

typedef struct {
    int width, height;
    int scrno;
    xcb_screen_t *scr;
    xcb_connection_t *connection;
    xcb_drawable_t win;
    unsigned int white;
    xcb_visualtype_t *visual_type;

    cairo_surface_t *surface;
    cairo_t *cr;
} Window;
Window window;

int makewindow()
{
    xcb_screen_iterator_t iter;
    xcb_depth_iterator_t depth_iter;
    uint32_t mask=0;
    uint32_t values[2];

    window.connection = xcb_connect(NULL,&window.scrno);
    iter = xcb_setup_roots_iterator(xcb_get_setup(window.connection));
    for (; iter.rem; --window.scrno, xcb_screen_next(&iter))
        if (window.scrno == 0)
        {
            window.scr = iter.data;
            break;
        }
    window.win = xcb_generate_id(window.connection);
    window.white = window.scr->white_pixel;
    mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    values[0] = window.white;
    values[1] = XCB_EVENT_MASK_EXPOSURE;
    xcb_create_window(window.connection, XCB_COPY_FROM_PARENT,
            window.win, window.scr->root,
            0, 0,
            window.width, window.height,
            5,
            XCB_WINDOW_CLASS_INPUT_OUTPUT,
            window.scr->root_visual,
            mask,
            values);
    xcb_icccm_set_wm_name(window.connection, window.win, XCB_ATOM_STRING, 8, strlen("xcr"), "xcr");
    xcb_map_window(window.connection, window.win);
    xcb_flush(window.connection);

    depth_iter = xcb_screen_allowed_depths_iterator(window.scr);
    for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
        xcb_visualtype_iterator_t visual_iter;

        visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
        for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
            if (window.scr->root_visual == visual_iter.data->visual_id) {
                window.visual_type = visual_iter.data;
                goto visual_found;
            }
        }
    }
visual_found: ;

    {
        window.surface = cairo_xcb_surface_create (window.connection,
                window.win, window.visual_type, window.width, window.height);
        window.cr = cairo_create (window.surface);

        //cairo_select_font_face (window.cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        //cairo_set_font_size (window.cr, 32.0);
        cairo_set_source_rgb (window.cr, 0.0, 0.0, 0.0);
        cairo_translate(window.cr, window.width / 2, window.width / 2);
        cairo_scale(window.cr, 1, -1);
        //cairo_move_to (window.cr, 10.0, 50.0);
        //cairo_show_text (window.cr, "Hello, world");

        //cairo_surface_flush(window.surface);
        //xcb_flush(window.connection);
    }
    return 0;
}

int destroywindow() {
    cairo_destroy (window.cr);
    cairo_surface_destroy (window.surface);
    xcb_disconnect(window.connection);
    return 0;
}

int gettime(int *hour, int *min, int *sec) {
    time_t t;
    struct tm *tm;
    time(&t);
    tm = localtime(&t);
    *hour = tm->tm_hour;
    *min = tm->tm_min;
    *sec = tm->tm_sec;
    return 0;
}

void drawclock(int x) {
    int hour, min, sec;
    double radius, centradius;
    int i, j;

    (void)x;
    signal(SIGALRM, drawclock);
    //hour = 0; min = 30; sec = 30;
    gettime(&hour, &min, &sec);
    hour %= 12;
    //printf("%02d:%02d:%02d\n", hour, min, sec);
    radius = (double)window.width / 2.0;
    radius -= 10.0;
    centradius = radius / 100.0;

    // Erase
    cairo_set_source_rgb(window.cr, 1.0, 1.0, 1.0);
    cairo_paint(window.cr);
    cairo_set_source_rgb(window.cr, 0.0, 0.0, 0.0);

    // Ticks
    for (i = 0; i < 12; i++){
        cairo_set_line_width(window.cr, 1);
        for (j = 0; j < 4; j++){
            cairo_rotate(window.cr, rad_deg(6));
            cairo_move_to(window.cr, radius, 0);
            cairo_rel_line_to(window.cr, (double)radius / 20.0, 0);
            cairo_stroke(window.cr);
        }
        cairo_set_line_width(window.cr, 3);
        cairo_rotate(window.cr, rad_deg(6));
        cairo_move_to(window.cr, radius, 0);
        cairo_rel_line_to(window.cr, (double)radius / 20.0, 0);
        cairo_stroke(window.cr);
    }

    // Hour hand
    cairo_save(window.cr);
        cairo_rotate(window.cr, rad_deg(90.0 - (60.0 * (double)hour + (double)min)/2));
        cairo_new_path(window.cr);
        cairo_move_to(window.cr, 0, 2);
        cairo_curve_to(window.cr, 15.0 * centradius, 3.0 * centradius,
                                  33.0 * centradius, 0,
                                  50.0 * centradius, 3.0 * centradius);
        cairo_curve_to(window.cr, 55.0 * centradius, 15.0 * centradius,
                                  60.0 * centradius, 0,
                                  76.0 * centradius, 0);
        cairo_curve_to(window.cr, 60.0 * centradius, 0,
                                  55.0 * centradius, -15.0 * centradius,
                                  50.0 * centradius, -3.0 * centradius);
        cairo_curve_to(window.cr, 33.0 * centradius, 0,
                                  15.0 * centradius, -3.0 * centradius,
                                  0, -2.0 * centradius);
        cairo_close_path(window.cr);
        cairo_set_source_rgb (window.cr, 0.0, 0.0, 0.677);
        cairo_fill(window.cr);
    cairo_restore(window.cr);

    // Minute hand
    cairo_save(window.cr);
        cairo_rotate(window.cr, rad_deg(90.0 - 6.0 * (double)min));
        cairo_new_path(window.cr);
        cairo_move_to(window.cr, 0, 2);
        cairo_curve_to(window.cr, 15.0 * centradius, 3.0 * centradius,
                                  33.0 * centradius, 0,
                                  50.0 * centradius, centradius);
        cairo_curve_to(window.cr, 65.0 * centradius, 3.0 * centradius,
                                  83.0 * centradius, 0,
                                  97.0 * centradius, 0);
        cairo_curve_to(window.cr, 83.0 * centradius, 0,
                                  65.0 * centradius, -3.0 * centradius,
                                  50.0 * centradius, -1.0 * centradius);
        cairo_curve_to(window.cr, 33.0 * centradius, 0,
                                  15.0 * centradius, -3.0 * centradius,
                                  0, -2.0 * centradius);
        cairo_close_path(window.cr);
        cairo_set_source_rgb (window.cr, 0.635, 0.0, 0.0);
        cairo_fill(window.cr);
    cairo_restore(window.cr);

    cairo_surface_flush(window.surface);
    xcb_flush(window.connection);

    //printf("alarm in %d\n", 60 - sec);
    alarm(60 - sec);
}

int main(int argc, char **argv)
{
    xcb_generic_event_t *e;
    window.width = window.height = 200;
    signal(SIGALRM, drawclock);

    makewindow();
    while (e = xcb_wait_for_event(window.connection)){
        switch(e->response_type & ~0x80){
        case XCB_EXPOSE:
            drawclock(0);
        }
        free(e);
        //sleep(1);
    }
    destroywindow();

    return 0;
}

okno xclock

luser droog
źródło
Spóźniłeś się na przyjęcie, ale to ładna odpowiedź. +1
Victor Stafusa
Dzięki. To zabawne pytanie. Aby to zrobić, musiałem nauczyć się kilku xcb. Napisałem okno Hello World jako kamień milowy w tym kierunku.
luser droog
1

Kliknij uruchom. Wyświetla się tylko co 30 minut, ponieważ zegar jest pojedynczym emoji.

function updateTick(){let e=new Date,t=e.getSeconds()+60*e.getMinutes()+e.getHours()%12*60*60,n=parseInt(t/3600*2)+1;document.documentElement.style.setProperty("--tick",n)}let d=new Date;setTimeout(()=>{setInterval(updateTick,18e5)},1e3*(d.getMinutes()+d.getSeconds())%30),updateTick();
@counter-style item{system:cyclic;symbols:"🕛" "🕧" "🕐" "🕜" "🕑" "🕝" "🕒" "🕞" "🕓" "🕟" "🕔" "🕠" "🕕" "🕡" "🕖" "🕢" "🕗" "🕣" "🕘" "🕤" "🕙" "🕥" "🕚" "🕦"}span.tik-terk-clerk::before{content:counters(item, "", item);counter-reset:item calc(var(--tick,1))}span.tik-terk-clerk::before{font-size:72pt}
<span class="tik-terk-clerk"></span>

adjenks
źródło
0

Tworzenie zegarów analogowych ma jakąś atrakcję dla osób uczących się programowania. W tym roku prowadzę zajęcia JavaScript, a moi uczniowie świetnie się bawili, kiedy wdrożyliśmy zegar analogowy za pomocą p5.js ...

Zegar analogowy wykonany przy użyciu p5.js

Kod źródłowy zegara analogowego jest dostępny na https://github.com/mveteanu/JSCourse

codeguppy
źródło
1
Witamy w PPCG! Zamiast zamieszczać tylko link do kodu, należy dołączyć kod do odpowiedzi.
Steadybox,
1
Witam i witam na stronie. Wygląda to na prawidłową odpowiedź, jednak ogólnie wolimy, jeśli kod został wstawiony w odpowiedzi niż link.
Wheat Wizard,