【问题标题】:Countdown Timer Image GIF in Email电子邮件中的倒数计时器图像 GIF
【发布时间】:2012-11-15 14:47:30
【问题描述】:

我最近收到了一封来自 Onnit Labs 的电子邮件,其中包含一个使用 gif 图像的电子邮件内的倒计时模块计时器。邮箱可以在这里查看:https://www.onnit.com/emails/lastchance-historic/

图片可以在这里看到:

我研究了一下,似乎您可以继续使用 gifsockets 将新帧发送到动画 GIF,因为 GIF 没有指定在浏览器中加载时它有多少帧。这是在github上:http://github.com/videlalvaro/gifsockets

我认为这确实很有趣,而且效果确实很酷。有没有人对如何实现这一点有任何其他见解?似乎他们在 Onnit 使用的那个似乎根据 URL 或图像末尾附加的日期更改了倒计时。

onnit.com/emails/_modules/timer/?end=2012-12-27+00:00:00&dark=1

我正在尝试完成相同的事情以发送电子邮件,但我有点难过。

【问题讨论】:

  • 似乎应该可以正常工作 - 只需发送带有 标记的 html 电子邮件,该标记的 'src' 属性引用 url。只要电子邮件阅读器正确呈现 html,URL 是由邮件阅读器还是浏览器访问都无关紧要。
  • 我下载了它生成的 gif,我只有 60 帧,这可能是他们需要的全部?邮件多长时间了?你会停留超过 60 秒吗?
  • 我也在浏览器中打开了一段时间,它似乎忘记了时间(我重新加载了 4 分钟)。
  • @GreyBeardedGeek 好吧,是的,如果我使用那里的 url 来托管图像,它会起作用,就像你说的那样,我只会将它包含在 标记中。我正在尝试用我自己的形象来实现这一点。我将如何去创造这样的东西?
  • @SeanJA gif 是无穷无尽的,具体取决于参数中 url 末尾附加的内容。 ?end=2012-12-27+00:00:00 对我来说,它似乎可以很好地跟踪时间。另外,重新加载它。

标签: sockets email timer gif countdown


【解决方案1】:

虽然gifsockets 可能会起作用(我之前没有尝试过...),但在我查看图像时除了初始图像加载之外没有网络流量。我也看到它再次从 41 跳到 42。重新加载将其降至 39。

它似乎只是一个脚本,可以生成 60 帧动画并将它们发送给用户。这可以用任何语言完成。

这是在 php 中的实现方式:

http://seanja.com/secret/countdown/

【讨论】:

  • 啊,幸运的是堆栈将图像保存在他们的服务器上,在链接中查看实时版本
  • 哇!惊人的,伟大的工作。这正是我一直在寻找的。我现在已经实现了你在这里所做的,所以你可以看到我是如何使用它的。 dev.alvaradom.com/test/countdown 我确实有一个问题是字符之间的间距如何。我正在使用另一种字体,并且间距已关闭。我现在的做法只是将 php 文件中的文本格式分开,就像这样 $text = $interval->format('00 : 00 : 00 : 00');在字体数组中,如果有一个间距参数('space'=>8,),那就太棒了!再次感谢!
  • 那会很方便 ;) 。不幸的是,你会有多轮 imagettftext 像这样:gist.github.com/4165467
  • 啊,我明白了,有道理。我厌倦了在这里查看这篇文章以获得一些见解,但我不是 PHP 大佬,所以我有点迷路了。不确定这是否有助于多轮 imagettftext stackoverflow.com/questions/6926613/… 但无论如何 - 你回答了我的问题 :) 谢谢!
  • SeanJA 你的回答太棒了,这就是我前一阵子投票的原因。我还做了一些您可能会喜欢的改进:stackoverflow.com/a/58250565/470749 我想知道您是否碰巧知道如何支持透明度?谢谢。
【解决方案2】:

我找到了http://sendtric.com/,它是免费的,而且很容易集成。

【讨论】:

  • 免费版也没有品牌,这很好
【解决方案3】:

你可以试试http://makedreamprofits.com/pt/。此倒计时不是为 gif 提供额外内容,而是分解为单独的图像,并且可以计数长达 20 分钟而不会增加太多流量。

附: Gmail 正在预缓存图像,因此无法无休止地为其提供新帧。

【讨论】:

  • 是的,这个答案来自 2012 年,它是 gmail 之前的缓存图像,现在套接字可能是一个更好的答案......我已经好几年没看这个了。
【解决方案4】:

我非常感谢 Sean Ja 的回答。 (他应该得到更多的支持。)然后我想让代码更具可读性和可配置性(并支持透明 gif 上的文本并自动居中文本):

use Carbon\Carbon;
class CountdownGifHelper {

    const DELAY = 100; /* Why was this labeled as 'milliseconds' when it seems like a value of 100 here causes 1 frame to be shown per second? */
    const MAX_FRAMES = 120;

    /**
     * 
     * @param string $bgImg
     * @param \DateInterval $interval
     * @param array $fontArr
     * @param array $frames
     * @param array $delays
     * @param string $format
     */
    public function addFrame($bgImg, $interval, $fontArr, &$frames, &$delays, $format) {
        $image = imagecreatefrompng($bgImg); //Each frame needs to start by creating a new image because otherwise the new numbers would draw on top of old ones. Here, it doesn't really matter what the PNG is (other than for size) because it's about to get filled with a new color.
        $text = $interval->format($format);
        ob_start();
        imageSaveAlpha($image, true);
        $backgroundColor = $fontArr['backgroundColor'];
        imagefill($image, 0, 0, $backgroundColor); //https://stackoverflow.com/a/17016252/470749 was a helpful hint
        imagecolortransparent($image, $backgroundColor);
        $this->insertCenteredText($image, $fontArr, $text);
        //imagettftext($image, $font['size'], $font['angle'], $font['x-offset'], $font['y-offset'], $font['color'], $font['file'], $text);//this was the old way
        imagegif($image); //The image format will be GIF87a unless the image has been made transparent with imagecolortransparent(), in which case the image format will be GIF89a.
        $frames[] = ob_get_contents();
        ob_end_clean();
        $delays[] = self::DELAY;
    }

    /**
     * 
     * @param resource $image
     * @param array $fontArray
     * @param string $text
     */
    public function insertCenteredText(&$image, $fontArray, $text) {
        $image_width = imagesx($image);
        $image_height = imagesy($image);
        $text_box = imagettfbbox($fontArray['size'], $fontArray['angle'], $fontArray['file'], $text); // Get Bounding Box Size
        $text_width = $text_box[2] - $text_box[0];
        $text_height = $text_box[7] - $text_box[1];
        // Calculate coordinates of the text https://stackoverflow.com/a/14517450/470749
        $x = ($image_width / 2) - ($text_width / 2);
        $y = ($image_height / 2) - ($text_height / 2);
        imagettftext($image, $fontArray['size'], $fontArray['angle'], $x, $y, $fontArray['color'], $fontArray['file'], $text);
    }

    /**
     * 
     * @param int $timestamp
     * @param string $bgImg
     * @param array $fontArray
     * @return string [can be used by Laravel response()->make($gifString, 200, $headers)]
     */
    public function getAnimatedGif($timestamp, $bgImg, $fontArray) {
        $future_date = Carbon::createFromTimestamp($timestamp);
        $time_now = time();
        $moment = new \DateTime(date('r', $time_now));
        $frames = [];
        $delays = [];
        for ($i = 0; $i <= self::MAX_FRAMES; $i++) {
            $interval = date_diff($future_date, $moment);
            if ($future_date < $moment) {
                $this->addFrame($bgImg, $interval, $fontArray, $frames, $delays, '00 : 00 : 00');
                $loops = 1; //stay stuck on this frame
                break;
            } else {
                $this->addFrame($bgImg, $interval, $fontArray, $frames, $delays, '%H : %I : %S');
                $loops = 0; //infinite loop
            }
            $moment->modify('+1 second');
        }
        $animatedGif = new \App\Helpers\AnimatedGif($frames, $delays, $loops, 0, 0, 0);
        return $animatedGif->getAnimation();
    }

    /**
     * ONEDAY allow config via params
     * @param resource $image
     * @return array
     */
    public function getFontArray($image) {
        $fontArr = [
            'file' => resource_path('assets/fonts/Kanit-Regular.ttf'),
            'size' => 30,
            //'x-offset' => 5,
            //'y-offset' => 30,
            'color' => imagecolorallocate($image, 90, 90, 90), //gray
            'backgroundColor' => imagecolorallocate($image, 0, 0, 0), //white. Must match the arguments provided to AnimatedGif (such as 0,0,0).
            'angle' => 0,
        ];
        return $fontArr;
    }

}

【讨论】:

    猜你喜欢
    • 2017-07-31
    • 1970-01-01
    • 1970-01-01
    • 2021-08-27
    • 2014-03-15
    • 2017-06-26
    • 1970-01-01
    • 2012-01-08
    相关资源
    最近更新 更多