MATLAB 中的 xkcd 风格图表

231

xkcd-style graph

有很多有才华的人已经想出了如何在Mathematica, LaTeX, PythonR中制作类似xkcd风格的图形。

那么如何使用MATLAB制作像上面那样的图形呢?

我尝试过的方法

我创建了抖动线,但是我无法得到抖动轴。我想到的唯一解决方案是用抖动线覆盖它们,但我希望能够更改实际的轴。我也无法让Humor字体起作用,所使用的代码段是:

 annotation('textbox',[left+left/8 top+0.65*top 0.05525 0.065],...
'String',{'EMBARRASSMENT'},...
'FontSize',24,...
'FontName','Humor',...
'FitBoxToText','off',...
'LineStyle','none');

对于波动线,我尝试添加了一些小的随机噪声并进行了平滑处理:
 smooth(0.05*randn(size(x)),10)

但我无法使它们相交时出现的白色背景消失...


9
编辑似乎满足了“先做一些基本研究”的要求。此外,这里的答案很好。重新开放。 - Shog9
4个回答

123
我看到有两种方法可以解决这个问题:第一种方法是向绘图特征的x/y坐标添加一些抖动。这种方法的优点是您可以轻松修改绘图,但如果要使它们变得像xkcd风格(参见@Rody Oldenhuis' solution),则必须自己绘制轴。第二种方法是创建一个非抖动的绘图,并使用imtransform对图像应用随机扭曲。这种方法的优点是您可以将其与任何绘图一起使用,但最终会得到一个图像,而不是可编辑的绘图。

首先我展示#2,然后展示我的#1尝试(如果您更喜欢#1,请查看Rody's solution!)。

enter image description here

这个解决方案依赖于两个关键函数:从文件交换中心获取抗锯齿截图的EXPORT_FIG,以及获取变换的IMTRANSFORM
%# define plot data
x = 1:0.1:10;
y1 = sin(x).*exp(-x/3) + 3;
y2 = 3*exp(-(x-7).^2/2) + 1;

%# plot
fh = figure('color','w');
hold on
plot(x,y1,'b','lineWidth',3);
plot(x,y2,'w','lineWidth',7);
plot(x,y2,'r','lineWidth',3);

xlim([0.95 10])
ylim([0 5])
set(gca,'fontName','Comic Sans MS','fontSize',18,'lineWidth',3,'box','off')

%# add an annotation 
 annotation(fh,'textarrow',[0.4 0.55],[0.8 0.65],...
     'string',sprintf('text%shere',char(10)),'headStyle','none','lineWidth',1.5,...
     'fontName','Comic Sans MS','fontSize',14,'verticalAlignment','middle','horizontalAlignment','left')

%# capture with export_fig
im = export_fig('-nocrop',fh);

%# add a bit of border to avoid black edges
im = padarray(im,[15 15 0],255);

%# make distortion grid
sfc = size(im);
[yy,xx]=ndgrid(1:7:sfc(1),1:7:sfc(2));
pts = [xx(:),yy(:)];
tf = cp2tform(pts+randn(size(pts)),pts,'lwm',12);
w = warning;
warning off images:inv_lwm:cannotEvaluateTransfAtSomeOutputLocations
imt = imtransform(im,tf);
warning(w)

%# remove padding
imt = imt(16:end-15,16:end-15,:);

figure('color','w')
imshow(imt)

这是我初步尝试抖动的结果。

enter image description here

%# define plot data
x = 1:0.1:10;
y1 = sin(x).*exp(-x/3) + 3;
y2 = 3*exp(-(x-7).^2/2) + 1;

%# jitter
x = x+randn(size(x))*0.01;
y1 = y1+randn(size(x))*0.01;
y2 = y2+randn(size(x))*0.01;

%# plot
figure('color','w')
hold on
plot(x,y1,'b','lineWidth',3);
plot(x,y2,'w','lineWidth',7);
plot(x,y2,'r','lineWidth',3);

xlim([0.95 10])
ylim([0 5])
set(gca,'fontName','Comic Sans MS','fontSize',18,'lineWidth',3,'box','off')

4
尽情享受在SO上的时间吧 [趁你还能!] (http://meta.stackexchange.com/a/41889/52738) ;) - gnovice
2
@gnovice:这将是我的第三个了。我希望现在我已经基本弄清楚了 :) - Jonas
@Jonas 做得好!我认为你的#2方案在所有解决方案中感觉最正确。然而,它仍然缺少大的波浪状刻度线、文本周围的框架以及手绘弯曲线条,以指向一条线... - bla
2
+1 用于 EXPORT_FIG。由于抗锯齿技术,我的所有图形看起来更加美观。 - Yamaneko
需要图像处理工具箱,如果有人遇到困难。 - N t
1
@JasonS:抱歉,那是我当时能够获得的最接近的东西。 - Jonas

97

我并不想重新实现所有各种绘图函数,而是创建一个通用工具,可以将任何现有的绘图转换为xkcd风格的绘图。

使用此方法,您可以使用标准的MATLAB函数创建绘图并为其设置样式,然后在完成绘图后,可以在保留总体样式的同时以xkcd风格重新呈现绘图。

示例

Plot 输入图片描述

Bar & Plot

输入图片描述

Box & Plot 输入图片描述

工作原理

该函数通过迭代axes的子项来工作。如果子项类型为linepatch,则会稍微扭曲它们。如果子项类型为hggroup,则会迭代hggroup的子项。我计划支持其他绘图类型,例如image,但目前尚不清楚将图像扭曲以具有xkcd风格的最佳方法是什么。

最后,为确保扭曲效果看起来均匀(即,短线与长线不会被扭曲得更多),我测量线的长度(以像素为单位),然后按比例上采样。然后我在每N个样本中添加噪声,这样产生的线就具有大致相同的扭曲量。

代码

不要贴上数百行代码,我只会链接到源代码的gist。此外,源代码和生成上述示例的代码可以在GitHub上自由获取。

从这些示例中可以看出,它还没有扭曲坐标轴本身,尽管我计划一旦找到最佳方法就立即实现。


4
好的!我一直在编写类似的代码,它实现了“export_fig”路线,即先将绘图格式化为xkcd风格,然后再对图片进行扭曲。 - Jonas
4
谢谢。我对箱线图真的感到自豪。我很惊讶需要多少技巧才能显示这些图。 - slayton
嗨,Slayton,这些看起来很棒!我只有一个问题,有没有办法也让坐标轴卡通/xkcd风格?那样对我来说就够了,我就可以使用它了!:-) 非常感谢... - Spacey
据我所知,Matlab没有提供任何API(文档或未记录的)来更改轴的呈现方式。 - slayton
@slayton - 使用标准绘图窗口命令来不绘制坐标轴,然后绘制类似于 x = 0:100, y = 0 + random(101,1)/20 的波浪线。 - Carl Witthoft
显示剩余2条评论

65

第一步是找到你喜欢的系统字体(使用listfonts函数查看可用字体),或者安装一个与xkcd的手写风格匹配的字体。我在这篇博客文章中发现了来自用户ch00f的一个TrueType字体“Humor Sans”,并将在后续示例中使用它。

依我看,通常需要三种不同的修改过的图形对象来制作这些类型的图表:一个axes对象,一个line对象和一个text对象。你可能还想要一个annotation对象使事情变得更容易,但我暂时放弃了它,因为它可能比上述三个对象更难实现。

我创建了包装函数来创建这三个对象,覆盖某些属性设置,使它们更像xkcd。一个限制是它们产生的新图形在某些情况下不会更新(例如调整轴时文本对象上的边界框),但这可以通过更完整的面向对象的实现来解决,涉及从句柄类继承,使用事件和侦听器等。现在,这是我的简单实现:

xkcd_axes.m:

function hAxes = xkcd_axes(xkcdOptions, varargin)

  hAxes = axes(varargin{:}, 'NextPlot', 'add', 'Visible', 'off', ...
               'XLimMode', 'manual', 'YLimMode', 'manual');

  axesUnits = get(hAxes, 'Units');
  set(hAxes, 'Units', 'pixels');
  axesPos = get(hAxes, 'Position');
  set(hAxes, 'Units', axesUnits);
  xPoints = round(axesPos(3)/10);
  yPoints = round(axesPos(4)/10);
  limits = [xlim(hAxes) ylim(hAxes)];
  ranges = [abs(limits(2) - limits(1)) abs(limits(4) - limits(3))];
  backColor = get(get(hAxes, 'Parent'), 'Color');
  xColor = get(hAxes, 'XColor');
  yColor = get(hAxes, 'YColor');
  line('Parent', hAxes, 'Color', xColor, 'LineWidth', 3, ...
       'Clipping', 'off', ...
       'XData', linspace(limits(1), limits(2), xPoints), ...
       'YData', limits(3) + rand(1, xPoints).*0.005.*ranges(2));
  line('Parent', hAxes, 'Color', yColor, 'LineWidth', 3, ...
       'Clipping', 'off', ...
       'YData', linspace(limits(3), limits(4), yPoints), ...
       'XData', limits(1) + rand(1, yPoints).*0.005.*ranges(1));

  xTicks = get(hAxes, 'XTick');
  if ~isempty(xTicks)
    yOffset = limits(3) - 0.05.*ranges(2);
    tickIndex = true(size(xTicks));
    if ismember('left', xkcdOptions)
      tickIndex(1) = false;
      xkcd_arrow('left', [limits(1) + 0.02.*ranges(1) xTicks(1)], ...
                 yOffset, xColor);
    end
    if ismember('right', xkcdOptions)
      tickIndex(end) = false;
      xkcd_arrow('right', [xTicks(end) limits(2) - 0.02.*ranges(1)], ...
                 yOffset, xColor);
    end
    plot([1; 1]*xTicks(tickIndex), ...
         0.5.*[-yOffset; yOffset]*ones(1, sum(tickIndex)), ...
         'Parent', hAxes, 'Color', xColor, 'LineWidth', 3, ...
         'Clipping', 'off');
    xLabels = cellstr(get(hAxes, 'XTickLabel'));
    for iLabel = 1:numel(xLabels)
      xkcd_text(xTicks(iLabel), yOffset, xLabels{iLabel}, ...
                'HorizontalAlignment', 'center', ...
                'VerticalAlignment', 'middle', ...
                'BackgroundColor', backColor);
    end
  end

  yTicks = get(hAxes, 'YTick');
  if ~isempty(yTicks)
    xOffset = limits(1) - 0.05.*ranges(1);
    tickIndex = true(size(yTicks));
    if ismember('down', xkcdOptions)
      tickIndex(1) = false;
      xkcd_arrow('down', xOffset, ...
                 [limits(3) + 0.02.*ranges(2) yTicks(1)], yColor);
    end
    if ismember('up', xkcdOptions)
      tickIndex(end) = false;
      xkcd_arrow('up', xOffset, ...
                 [yTicks(end) limits(4) - 0.02.*ranges(2)], yColor);
    end
    plot(0.5.*[-xOffset; xOffset]*ones(1, sum(tickIndex)), ...
         [1; 1]*yTicks(tickIndex), ...
         'Parent', hAxes, 'Color', yColor, 'LineWidth', 3, ...
         'Clipping', 'off');
    yLabels = cellstr(get(hAxes, 'YTickLabel'));
    for iLabel = 1:numel(yLabels)
      xkcd_text(xOffset, yTicks(iLabel), yLabels{iLabel}, ...
                'HorizontalAlignment', 'right', ...
                'VerticalAlignment', 'middle', ...
                'BackgroundColor', backColor);
    end
  end

  function xkcd_arrow(arrowType, xArrow, yArrow, arrowColor)
    if ismember(arrowType, {'left', 'right'})
      xLine = linspace(xArrow(1), xArrow(2), 10);
      yLine = yArrow + rand(1, 10).*0.003.*ranges(2);
      arrowScale = 0.05.*ranges(1);
      if strcmp(arrowType, 'left')
        xArrow = xLine(1) + arrowScale.*[0 0.5 1 1 1 0.5];
        yArrow = yLine(1) + arrowScale.*[0 0.125 0.25 0 -0.25 -0.125];
      else
        xArrow = xLine(end) - arrowScale.*[0 0.5 1 1 1 0.5];
        yArrow = yLine(end) + arrowScale.*[0 -0.125 -0.25 0 0.25 0.125];
      end
    else
      xLine = xArrow + rand(1, 10).*0.003.*ranges(1);
      yLine = linspace(yArrow(1), yArrow(2), 10);
      arrowScale = 0.05.*ranges(2);
      if strcmp(arrowType, 'down')
        xArrow = xLine(1) + arrowScale.*[0 0.125 0.25 0 -0.25 -0.125];
        yArrow = yLine(1) + arrowScale.*[0 0.5 1 1 1 0.5];
      else
        xArrow = xLine(end) + arrowScale.*[0 -0.125 -0.25 0 0.25 0.125];
        yArrow = yLine(end) - arrowScale.*[0 0.5 1 1 1 0.5];
      end
    end
    line('Parent', hAxes, 'Color', arrowColor, 'LineWidth', 3, ...
         'Clipping', 'off', 'XData', xLine, 'YData', yLine);
    patch('Parent', hAxes, 'FaceColor', arrowColor, ...
          'EdgeColor', arrowColor, 'LineWidth', 2, 'Clipping', 'off', ...
          'XData', xArrow + [0 rand(1, 5).*0.002.*ranges(1)], ...
          'YData', yArrow + [0 rand(1, 5).*0.002.*ranges(2)]);
  end

end

xkcd_text.m:

function hText = xkcd_text(varargin)

  hText = text(varargin{:});
  set(hText, 'FontName', 'Humor Sans', 'FontSize', 13, ...
      'FontWeight', 'normal');

  backColor = get(hText, 'BackgroundColor');
  edgeColor = get(hText, 'EdgeColor');
  if ~strcmp(backColor, 'none') || ~strcmp(edgeColor, 'none')
    hParent = get(hText, 'Parent');
    extent = get(hText, 'Extent');
    nLines = size(get(hText, 'String'), 1);
    extent = extent + [-0.5 -0.5 1 1].*0.25.*extent(4)./nLines;
    yPoints = 5*nLines;
    xPoints = round(yPoints*extent(3)/extent(4));
    noiseScale = 0.05*extent(4)/nLines;
    set(hText, 'BackgroundColor', 'none', 'EdgeColor', 'none');
    xBox = [linspace(extent(1), extent(1) + extent(3), xPoints) ...
            extent(1) + extent(3) + noiseScale.*rand(1, yPoints) ...
            linspace(extent(1) + extent(3), extent(1), xPoints) ...
            extent(1) + noiseScale.*rand(1, yPoints)];
    yBox = [extent(2) + noiseScale.*rand(1, xPoints) ...
            linspace(extent(2), extent(2) + extent(4), yPoints) ...
            extent(2) + extent(4) + noiseScale.*rand(1, xPoints) ...
            linspace(extent(2) + extent(4), extent(2), yPoints)];
    patch('Parent', hParent, 'FaceColor', backColor, ...
          'EdgeColor', edgeColor, 'LineWidth', 2, 'Clipping', 'off', ...
          'XData', xBox, 'YData', yBox);
    hKids = get(hParent, 'Children');
    set(hParent, 'Children', [hText; hKids(hKids ~= hText)]);
  end

end

xkcd_line.m:

function hLine = xkcd_line(xData, yData, varargin)

  yData = yData + 0.01.*max(range(xData), range(yData)).*rand(size(yData));
  line(xData, yData, varargin{:}, 'Color', 'w', 'LineWidth', 8);
  hLine = line(xData, yData, varargin{:}, 'LineWidth', 3);

end

这里是一个示例脚本,使用它们重新创建上面的漫画。我使用 ginput 标记鼠标在图中的点,捕获它们,然后按照自己的方式绘制它们:

xS = [0.0359 0.0709 0.1004 0.1225 0.1501 0.1759 0.2219 0.2477 0.2974 0.3269 0.3582 0.3895 0.4061 0.4337 0.4558 0.4797 0.5074 0.5276 0.5589 0.5810 0.6013 0.6179 0.6271 0.6344 0.6381 0.6418 0.6529 0.6713 0.6842 0.6934 0.7026 0.7118 0.7265 0.7376 0.7560 0.7726 0.7836 0.7965 0.8149 0.8370 0.8573 0.8867 0.9033 0.9346 0.9659 0.9843 0.9936];
yS = [0.2493 0.2520 0.2548 0.2548 0.2602 0.2629 0.2629 0.2657 0.2793 0.2657 0.2575 0.2575 0.2602 0.2629 0.2657 0.2766 0.2793 0.2875 0.3202 0.3856 0.4619 0.5490 0.6771 0.7670 0.7970 0.8270 0.8433 0.8433 0.8243 0.7180 0.6199 0.5272 0.4510 0.4128 0.3392 0.2711 0.2275 0.1757 0.1485 0.1131 0.1022 0.0858 0.0858 0.1022 0.1267 0.1567 0.1594];

xF = [0.0304 0.0488 0.0727 0.0967 0.1335 0.1630 0.2090 0.2348 0.2698 0.3011 0.3269 0.3545 0.3803 0.4153 0.4466 0.4724 0.4945 0.5110 0.5350 0.5516 0.5608 0.5700 0.5755 0.5810 0.5884 0.6013 0.6179 0.6363 0.6492 0.6584 0.6676 0.6731 0.6842 0.6860 0.6934 0.7007 0.7136 0.7265 0.7394 0.7560 0.7726 0.7818 0.8057 0.8444 0.8794 0.9107 0.9475 0.9751 0.9917];
yF = [0.0804 0.0940 0.0967 0.1049 0.1185 0.1458 0.1512 0.1540 0.1649 0.1812 0.1812 0.1703 0.1621 0.1594 0.1703 0.1975 0.2411 0.3065 0.3801 0.4782 0.5708 0.6526 0.7452 0.8106 0.8324 0.8488 0.8433 0.8270 0.7888 0.7343 0.6826 0.5981 0.5300 0.4782 0.3910 0.3420 0.2847 0.2248 0.1621 0.0995 0.0668 0.0395 0.0232 0.0177 0.0204 0.0232 0.0259 0.0204 0.0232];

xE = [0.0267 0.0488 0.0856 0.1409 0.1759 0.2164 0.2514 0.3011 0.3269 0.3637 0.3969 0.4245 0.4503 0.4890 0.5313 0.5608 0.5939 0.6344 0.6694 0.6934 0.7192 0.7394 0.7523 0.7689 0.7891 0.8131 0.8481 0.8757 0.9070 0.9346 0.9604 0.9807 0.9936];
yE = [0.0232 0.0232 0.0232 0.0259 0.0259 0.0259 0.0313 0.0259 0.0259 0.0259 0.0368 0.0395 0.0477 0.0586 0.0777 0.0886 0.1213 0.1730 0.2466 0.2902 0.3638 0.5082 0.6499 0.7916 0.8924 0.9414 0.9550 0.9387 0.9060 0.8760 0.8542 0.8379 0.8188];

hFigure = figure('Position', [300 300 700 450], 'Color', 'w');
hAxes = xkcd_axes({'left', 'right'}, 'XTick', [0.45 0.60 0.7 0.8], ...
                  'XTickLabel', {'YARD', 'STEPS', 'DOOR', 'INSIDE'}, ...
                  'YTick', []);

hSpeed = xkcd_line(xS, yS, 'Parent', hAxes, 'Color', [0.5 0.5 0.5]);
hFear = xkcd_line(xF, yF, 'Parent', hAxes, 'Color', [0 0.5 1]);
hEmb = xkcd_line(xE, yE, 'Parent', hAxes, 'Color', 'r');

hText = xkcd_text(0.27, 0.9, ...
                  {'WALKING BACK TO MY'; 'FRONT DOOR AT NIGHT:'}, ...
                  'Parent', hAxes, 'EdgeColor', 'k', ...
                  'HorizontalAlignment', 'center');

hSpeedNote = xkcd_text(0.36, 0.35, {'FORWARD'; 'SPEED'}, ...
                       'Parent', hAxes, 'Color', 'k', ...
                       'HorizontalAlignment', 'center');
hSpeedLine = xkcd_line([0.4116 0.4282 0.4355 0.4411], ...
                       [0.3392 0.3256 0.3038 0.2820], ...
                       'Parent', hAxes, 'Color', 'k');
hFearNote = xkcd_text(0.15, 0.45, {'FEAR'; 'THAT THERE''S'; ...
                                   'SOMETHING'; 'BEIND ME'}, ...
                      'Parent', hAxes, 'Color', 'k', ...
                      'HorizontalAlignment', 'center');
hFearLine = xkcd_line([0.1906 0.1998 0.2127 0.2127 0.2201 0.2256], ...
                      [0.3501 0.3093 0.2629 0.2221 0.1975 0.1676], ...
                      'Parent', hAxes, 'Color', 'k');
hEmbNote = xkcd_text(0.88, 0.45, {'EMBARRASSMENT'}, ...
                     'Parent', hAxes, 'Color', 'k', ...
                     'HorizontalAlignment', 'center');
hEmbLine = xkcd_line([0.8168 0.8094 0.7983 0.7781 0.7578], ...
                     [0.4864 0.5436 0.5872 0.6063 0.6226], ...
                     'Parent', hAxes, 'Color', 'k');

这里是最终的图表:(高音喇叭声)

输入图片描述


2
太棒了!我唯一的建议是指向文本的线条应该更细,更弯曲(不要那么抖动)。 - bla
4
这很棒,尽管情节受到了混淆的影响。我在这里写了一篇简短的文章,介绍如何处理这个问题:http://hugocarr.com/index/xkcd-style-graphs-in-matlab/ - Huguenot

29

好的,那么这是我稍微委婉一些但还不够完美的尝试:

%# init
%# ------------------------

noise = @(x,A) A*randn(size(x));
ns    = @(x,A) A*ones(size(x));


h = figure(2); clf, hold on
pos = get(h, 'position');
set(h, 'position', [pos(1:2) 800 450]);


blackline = {
    'k', ...
    'linewidth', 2};
axisline = {
    'k', ...
    'linewidth', 3};

textprops = {
    'fontName','Comic Sans MS',...
    'fontSize', 14,...
    'lineWidth',3};


%# Plot data
%# ------------------------
x  = 1:0.1:10;

y0 = sin(x).*exp(-x/30) + 3;
y1 = sin(x).*exp(-x/3) + 3;
y2 = 3*exp(-(x-7).^6/.05) + 1;

y0 = y0 + noise(x, 0.01);
y1 = y1 + noise(x, 0.01);
y2 = y2 + noise(x, 0.01);

%# plot
plot(x,y0, 'color', [0.7 0.7 0.7], 'lineWidth',3);

plot(x,y1, 'w','lineWidth',7);
plot(x,y1, 'b','lineWidth',3);

plot(x,y2, 'w','lineWidth',7);
plot(x,y2, 'r','lineWidth',3);




%# text
%# ------------------------
ll(1) = text(1.3, 4.2,...
    {'Walking back to my'
    'front door at night:'});

ll(2) = text(5, 0.7, 'yard');
ll(3) = text(6.2, 0.7, 'steps');
ll(4) = text(7, 0.7, 'door');
ll(5) = text(8, 0.7, 'inside');

set(ll, textprops{:});


%# arrows & lines
%# ------------------------

%# box around "walking back..."
xx = 1.2:0.1:3.74;
yy = ns(xx, 4.6) + noise(xx, 0.007);
plot(xx, yy, blackline{:})

xx = 1.2:0.1:3.74;
yy = ns(xx, 3.8) + noise(xx, 0.007);
plot(xx, yy, blackline{:})

yy = 3.8:0.1:4.6;
xx = ns(yy, 1.2) + noise(yy, 0.007);
plot(xx, yy, blackline{:})

xx = ns(yy, 3.74) + noise(yy, 0.007);
plot(xx, yy, blackline{:})

%# left arrow
x_arr = 1.2:0.1:4.8;
y_arr = 0.65 * ones(size(x_arr)) + noise(x_arr, 0.005);
plot(x_arr, y_arr, blackline{:})
x_head = [1.1 1.6 1.62];
y_head = [0.65 0.72 0.57];
patch(x_head, y_head, 'k')

%# right arrow
x_arr = 8.7:0.1:9.8;
y_arr = 0.65 * ones(size(x_arr)) + noise(x_arr, 0.005);
plot(x_arr, y_arr, blackline{:})
x_head = [9.8 9.3 9.3];
y_head = [0.65 0.72 0.57];
patch(x_head, y_head, 'k')

%# left line on axis
y_line = 0.8:0.1:1.1;
x_line = ns(y_line, 6.5) + noise(y_line, 0.005);
plot(x_line, y_line, blackline{:})

%# right line on axis
y_line = 0.8:0.1:1.1;
x_line = ns(y_line, 7.2) + noise(y_line, 0.005);
plot(x_line, y_line, blackline{:})

%# axes
x_xax = x;
y_xax = 0.95 + noise(x_xax, 0.01);
y_yax = 0.95:0.1:5;
x_yax = x(1) + noise(y_yax, 0.01);
plot(x_xax, y_xax, axisline{:})
plot(x_yax, y_yax, axisline{:})


% finalize 
%# ------------------------

xlim([0.95 10])
ylim([0 5])
axis off

结果:

XKCD风格的Matlab图示

要做的事情:

  1. 寻找更好的函数(最好分段定义)
  2. 添加“注释”和波浪线以描述曲线
  3. 寻找比Comic Sans更好的字体!
  4. 将所有内容概括为一个名为plot2xkcd的函数,以便我们可以将任何绘图/图表转换成xkcd风格。

1
颜色和坐标轴做得很好!不过我感觉它们有点太抖动了。无论如何,还是给你点赞。 - Jonas
@HighPerormanceMark:我仍然认为这并不是非常有用的,但是它非常有趣 :) - Rody Oldenhuis
@RodyOldenhuis为什么不实用?我发现样式化的图形比原始图形更美观。添加样式确实是一项有效的功能。 - slayton
2
@slayton:让我们来看一个非常先进的数字计算工具,它被设计成超级高效,能够制作出精确无误、美观易读的图表,然后我们用它来做……漫画。抱歉,这太荒谬了。不过这真的很有趣,这也是为什么大多数人在这里点赞并重新打开问题的原因。这对未来的访问者有用吗?嗯……它确实会激发灵感。也许它会邀请一些人学习Matlab。但是要使xkcd风格的作品正常运行,需要使用一些技巧和方法,这些方法可能是有问题的,至少是值得怀疑的 :) - Rody Oldenhuis
6
我会在我的演示中使用这些图表。通常是通过“hack”才能真正了解环境的运作方式。 - Jonas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接