【问题标题】:create gradient filled arrow in base R在基础 R 中创建渐变填充箭头
【发布时间】:2014-09-14 21:55:04
【问题描述】:

我正在寻找一种将箭头添加到基础 R 中的绘图的方法,这样箭头将填充灰色渐变色,如下所示:

我已经看到this 解决方案,但这似乎相当复杂且不那么灵活:我需要在很多地块中绘制一个很棒的箭头,所有这些都可能具有不同的长度和宽度。 我知道shape 包,但这似乎只能填充箭头,并且不提供箭头的可填充“基础”。 有什么建议吗?

【问题讨论】:

  • Base R 并没有真正处理渐变,你必须通过绘制一堆不同颜色的小矩形来伪造它。您基本上有一个要创建的非常简单的多边形形状。如果您可以只在箭头尾部使用渐变,事情就更容易了。但是您需要更具体地说明您对我的要求。您希望如何能够具体,宽度,长度,头部大小,渐变颜色值,方向等。这个问题缺乏具体的细节来回答它的当前状态。
  • 为了强调@MrFlick 的cmets,大多数R-Core 认为这是为了模仿Excel 和PowerPoint 强加给世界的臭名昭著的图表垃圾技术。真正的统计学家让数据自己说话。
  • @BondedDust 渐变色可以传达有意义的数据,这就是它们在ggplot中实现的原因。我怀疑 R-Core 不实施渐变的决定是一个优先事项,而不是意识形态。
  • 我同意@nograpes,渐变填充确实很有意义。虽然这可能很少见,但 OP 的问题是有效的,如果他需要这些符号,为什么不帮助他呢?无论如何,多边形可以用渐变填充,我可以理解人们也想用这种方式填充箭头形状的符号。

标签: r


【解决方案1】:

按照@MrFlick 的建议,这是帮助您入门的一种方法。您可能希望将其封装在一个函数中,以便您对箭头的大小、底部和箭头的宽度、渐变的平滑度等施加更多影响。

#empty box
plot(c(-1, 2), c(-1, 10), ,type="n",axes=FALSE, xlab = "", ylab = "")
# plot the arrow, without a fill
polygon(c(0,0,-.25,.5,1.25,1,1,0), y = c(0,6,6, 8,6,6,0,0), border = NA)
# create gradient colors
nslices = 100
cols <- colorRampPalette(colors = c("white", "black"))(nslices)
# split the base of the arrow in nslices and fill each progressively
ys <- seq(0,6, len = nslices + 1)
for (i in 1:nslices) {
  polygon(c(0,0,1,1), c(ys[i], ys[i+1], ys[i+1], ys[i]), col = cols[i], border = NA)
}
# add a filled arrowhead
polygon(c(-.25, .5, 1.25, -.25), c(6, 8, 6, 6), col = "black")

这会给你一个像这样的箭头:

HTH,彼得

【讨论】:

  • 你可以一次绘制所有多边形,使用 NA 来分隔 xy 坐标
  • 谢谢,这是一个简单的解决方案。事实上,我需要把它变成一个函数,让它更通用。
  • 请注意箭头的颜色是统一的(这可能是可取的,也可能不是可取的)
  • 这对我的应用程序来说并不重要,但对于其他用途来说确实很重要。
【解决方案2】:

使用链接问题中定义的箭头,现在在基本图形中

# create a black arrow, saved as external file
library(grid)
png("mask.png")
grid.polygon(c(-0.06, 0.06, 0.06, 0.15, 0, -0.15, -0.06),
             c(-5, -5, 2.5, 2, 5, 2, 2.5), gp=gpar(fill="black"),
             def="native",
             vp=viewport(xs=c(-0.15, 0.15), ys=c(-5, 5)))
dev.off()

## read back in as colour matrix
library(png)
m <- readPNG("mask.png", native=FALSE)
mask <- matrix(rgb(m[,,1],m[,,2],m[,,3]),
               nrow=nrow(m))

rmat <- matrix(grey(seq(0,1,length=nrow(m))),
               nrow=nrow(m), ncol=ncol(m))
rmat[mask == "#FFFFFF"] <- NA


## use in base plot
set.seed(12321)
plot(1:10, rnorm(10))
rasterImage(rmat, 2, -1, 2.5, 0)

编辑:

不必使用临时文件来创建掩码,它比摆弄逻辑矩阵(更)方便。这是直接将箭头创建为矩阵的起点,

marrow <- function(nr=500, nc=300, col = grey(seq(0, 1, length=nr))){

  skin <- matrix(col, nrow=nr, ncol=nc)
  head <- lower.tri(matrix(TRUE, nrow=nc/2, ncol=nc/2))
  skull <- cbind(head[seq(nc/2,1),], head[seq(nc/2,1),seq(nc/2,1)])

  rib <- matrix(TRUE, nrow=nr-nrow(skull), ncol=nc/4)
  trunk <- cbind(rib, !rib, !rib, rib)
  skeleton <- rbind(skull, trunk)
  skin[skeleton] <-  NA_character_
  skin
}

grid.newpage()
grid.raster(marrow(), 
            width = unit(1,"npc"), 
            height=unit(1,"npc"))

【讨论】:

  • 嗨巴蒂斯特,这很有趣。我以前见过这种方法,并且喜欢它所允许的灵活性。我有点犹豫是否必须保存 png,因为当我的同事也使用该功能时,这有点棘手。我宁愿绕过中间文件的保存和读取。是否可以简单地将信息存储在对象中,而不将其作为 png 保存到文件中?
  • 当然,您可以一劳永逸地保存矩阵mmask 甚至rmat,但您将无法更改分辨率和一般形状(除了拉伸)。
  • 打印结果图时,拉伸会影响分辨率/清晰度吗?我需要一堆箭头,它们的宽度和长度各不相同,并且需要它们都具有打印质量。谢谢。
  • 很难说,这取决于原始png文件的分辨率以及你将它拉伸多少。
猜你喜欢
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多