Подтвердить что ты не робот

R график: есть ли способ нарисовать границу, тень или буфер вокруг текстовых меток?

Я хочу нанести метку на линию в монохромном изображении. Поэтому мне нужна маленькая белая рамка на каждой букве этикетки.

Граница или фон прямоугольника текстовой метки бесполезны, поскольку скрывают много данных, нанесенных на график.

Есть ли способ поместить границы, тени или буфера вокруг текстовых меток на графиках R?

РЕДАКТИРОВАТЬ:

shadowtext <- function(x, y=NULL, labels, col='white', bg='black',
                   theta= seq(pi/4, 2*pi, length.out=8), r=0.1, ... ) {

  xy <- xy.coords(x,y)
  xo <- r*strwidth('x')
  yo <- r*strheight('x')

  for (i in theta) {
    text( xy$x + cos(i)*xo, xy$y + sin(i)*yo, labels, col=bg, ... )
  }
  text(xy$x, xy$y, labels, col=col, ... )
}

pdf(file="test.pdf", width=2, height=2); par(mar=c(0,0,0,0)+.1)
  plot(c(0,1), c(0,1), type="l", lwd=20, axes=FALSE, xlab="", ylab="")
  text(1/6, 1/6, "Test 1")
  text(2/6, 2/6, "Test 2", col="white")
  shadowtext(3/6, 3/6, "Test 3")
  shadowtext(4/6, 4/6, "Test 4", col="black", bg="white")
  shadowtext(5/6, 5/6, "Test 5", col="black", bg="white", theta = seq(pi/4, 2*pi, length.out=24))
dev.off()

Приведенный выше код использует решение от koekenbakker. Это хорошо для графики PNG, но мне нужен другой подход для PDF с высоким разрешением.

4b9b3361

Ответ 1

Вы можете попробовать эту функцию "shadowtext", которая рисует ореол или границу вокруг текста, печатая его несколько раз с небольшим смещением в другом цвете. Все кредиты Грег Сноу здесь.

shadowtext <- function(x, y=NULL, labels, col='white', bg='black', 
                       theta= seq(0, 2*pi, length.out=50), r=0.1, ... ) {

    xy <- xy.coords(x,y)
    xo <- r*strwidth('A')
    yo <- r*strheight('A')

    # draw background text with small shift in x and y in background colour
    for (i in theta) {
        text( xy$x + cos(i)*xo, xy$y + sin(i)*yo, labels, col=bg, ... )
    }
    # draw actual text in exact xy position in foreground colour
    text(xy$x, xy$y, labels, col=col, ... )
}

# And here is an example of use:
# pdf(file="test2.pdf", width=2, height=2); par(mar=c(0,0,0,0)+.1)
plot(c(0,1), c(0,1), type="n", lwd=20, axes=FALSE, xlab="", ylab="")

rect(xleft = 0.5, xright = 1, ybottom = 0, ytop = 1, col=1)
text(1/6, 1/6, "Test 1")
shadowtext(2/6, 2/6, "Test 2", col='red', bg="blue")
shadowtext(3/6, 3/6, "Test 3", cex=2)

# `r` controls the width of the border
shadowtext(5/6, 5/6, "Test 4", col="black", bg="white", cex=4, r=0.2)
# dev.off()

enter image description here

Ответ 2

Мне нужно было сделать это для карты в R, и в итоге я использовал пакет "растр" для рисования ореолов вокруг текстовых меток.

http://rpackages.ianhowson.com/cran/raster/man/text.html

например,

library(raster)

text(Points, labels = Points$Labels, halo = TRUE, hw = 0.08, hc = "white", cex = 0.8)
# hw = halo width
# hc = halo color

enter image description here

Ответ 3

Пакет shadowtext можно использовать для рисования контура или тени вокруг текста для ggplot2.

library(ggplot2)
library(shadowtext)

jet.colors <- colorRampPalette(c("#00007F", "blue", "#007FFF", "cyan", "#7FFF7F", 
                                 "yellow", "#FF7F00", "red", "#7F0000"))

### Note: jet (rainbow) is not color-blind friendly, not perceptually uniform, and can be misleading 
# so please don't use it for your plots
# https://blogs.egu.eu/divisions/gd/2017/08/23/the-rainbow-colour-map/
# https://www.nature.com/articles/519291d
# Choose viridis instead https://cran.r-project.org/web/packages/viridis/vignettes/intro-to-viridis.html
# I only use jet here for the demonstration of the 'shadowtext' package.

ggplot(faithfuld, aes(waiting, eruptions)) +
  geom_raster(aes(fill = density)) +
  scale_fill_gradientn(colors = jet.colors(7)) +
  geom_shadowtext(aes(x = 75, y = 4.5),
    label = "White text with black outline\nwill be visible on any background",
    check_overlap = TRUE,
    size = 8) +
  theme_minimal()

Создано в 2018-10-14 пакетом представлением (v0.2.1.9000)

Ответ 4

Я написал аналогичную функцию для текстовых полей, которая также работает с логарифмическими шкалами.

install.packages("berryFunctions")
library("berryFunctions")
?textField

Это может считаться более приятным для векторной графики. Вот несколько примеров:

enter image description here

PS: Если вы хотите внести свой вклад: https://github.com/brry/berryFunctions

Ответ 5

Вот моя попытка добавить текстовый буфер при маркировке контуров (или кругов в этом примере). Это определенно не так эффективно или красиво, как решение koekenbakker, но это послужило для меня целью изолировать текстовую метку от линии.

require(shape)
plot(250,250, xlim=c(0,500), ylim=c(0,500), axes=F, ylab="", xlab="", col="black") ## set up the plotting area

circle_radius<-c(200, 150, 50) ## we wan't to draw a few circles which we will label after using our buffer

for (i in 1:length(circle_radius)){
    plotcircle(mid=c(250,250), r=circle_radius[i], lwd=0.5,lcol="grey40") ## iteratively plot the circles

text_buffer<-seq(0.1, 0.7, by=0.01) ## this is the key to the text buffer. Create a vector of values to set the character size (cex) during the following loop

for(j in text_buffer){
    text(x=250+circle_radius[i], 250, print(paste(circle_radius[i],"m")), cex=j, srt=270, col="white") ## write the text buffer in white starting from the smallest value of cex to the largest
}  ## end of loop for writing buffer
    text(x=250+circle_radius[i], 250, print(paste(circle_radius[i],"m")), cex=0.5, srt=270) ## write over the buffer with black text

}  ## end of loop for drawing circles

Plot of circles with text buffers