1

Is it possible to do inside stroke at SKShapeNode? By default, it encircles the middle line. For example, if stroke 6 pixels, 3 pixel will be on one side, other 3 pixels to the other side... it is necessary that all 6 pixels were on the inside.

P.S. Sorry for my English.

Example stroke image

toha
  • 5,095
  • 4
  • 40
  • 52
xXxxX
  • 205
  • 1
  • 8
  • Just make the shape 3 pixels (using the provided example) smaller on each dimension, that way the stroke is where you want it – Nik Sep 23 '16 at 13:22
  • @Nik, visually that is a good answer, but will it affect the actual size of the shape (We want a 12 by 12 box, so we make it 6x6 to compensate for the 3 pixel outside stroke, does it make the final shape 12x12 or 6x6) – Knight0fDragon Sep 23 '16 at 13:26
  • @Knight0fDragon Right... If he/she is using this for an important piece of the game, should they be using an image (SKSpriteNode) instead though? I've heard that SKShapeNodes have caused problems before. I.e. Memory leaks, lag, etc... – Nik Sep 23 '16 at 13:32
  • @Nik, no idea if they fixed it in iOS 10, but there is reason to use `SKShapeNode` over `SKSpriteNode`, just depends on the design. Like in this case, using stroke. If we were to scale the shape, the stroke would stay the same size, (I think, I don't use it often, if it doesn't then use "resize the shape") This would not work in `SKSpriteNode`, the border would get fatter – Knight0fDragon Sep 23 '16 at 13:36
  • @Knight0fDragon Ok then. That's nice to know. For what you said/asked earlier about the stroke not being part of the shape, I would think that the stroke counts as part of the shape. I'm not 100% sure, but I vaguely remember testing this a while ago... I'll check now too – Nik Sep 23 '16 at 13:39
  • @Knight0fDragon I just checked it and when I clicked/tapped on the outermost part of the stroke, it identified it as part of the shape – Nik Sep 23 '16 at 13:45
  • @Nik, ok cool, then you provided a valid answer, make is an answer, I will give you an upvote – Knight0fDragon Sep 23 '16 at 13:46
  • I guess the only other concern is how the blending happens – Knight0fDragon Sep 23 '16 at 13:47
  • @Knight0fDragon Thanks. And what do you mean about blending? (Sorry if that's a basic question) – Nik Sep 23 '16 at 13:49
  • @Nik, like in the picture above, if your stroke color has an alpha < 1, then it blends half in the shape, half out, not like what the OP wants, 100% blend done internally – Knight0fDragon Sep 23 '16 at 13:54
  • @Knight0fDragon Hmmm... I'm not sure how to do that. Maybe I'm not understanding this correctly, but doesn't the OP want it all one colour though? I think the colour difference is just there to explicitly show where the stroke is inside and outside the shape. – Nik Sep 23 '16 at 13:58
  • @Nik, I am just saying IF there was stroke color with an alpha < 1, your solution does not work 100% – Knight0fDragon Sep 23 '16 at 14:00
  • @Knight0fDragon Ok. Sorry. I didn't fully understand what you were saying. I can't think of a solution of the top of my head, but if I think of one I'll add it to my answer. If you know a way, feel free to put that as an answer or add it to mine if you want – Nik Sep 23 '16 at 14:03

2 Answers2

3

Important: This doesn't give a good look if you use an alpha of less than 1 for the stroke because of the colour blending between the stroke colour and shape colour.

Make the shape 3 pixels (using the provided example from the question) smaller in each direction (up, down, left, and right), that way the stroke is where you want it. Since the stroke counts as part of the shape, you don't have to worry about the size of the shape being smaller and when you touch the stroke it still counts as touching the shape.

Although the stroke remains half inside and half outside the new shape, the stroke is on the inside of where the original shape was and gives the look of being the same size as the original shape, while the stroke looks like it's fully on the inside.

Note that to get the amount of pixels you need to shrink the shape in each dimension by, just divide the size of the desired stroke by 2.

If you're trying to "put" the stroke on the outside of the shape, instead of decreasing the shape by however many pixels, simply increase it by the same amount on every direction.

Keep in mind that this is more of a hack than solution because there is no way (that I know of at least) to move the stroke to the inside or outside of a shape.

Nik
  • 1,664
  • 2
  • 14
  • 27
  • If you make the shape 3 pixels smaller, why doesn't the stroke/outline also shrink its position by 3 pixels? – Confused Sep 23 '16 at 15:20
  • @Confused I don't fully understand what you're asking, but I'll take a crack at it. Shrinking the shape by 3 pixels (using the example) changes a shape so instead of having the stroke half inside the originally desired shape size and half outside, it looks like the stroke is all on the inside of the originally sized shape. However the shape has just been shrunken/downsized in every dimension to give this effect – Nik Sep 23 '16 at 15:23
  • But isn't the stroke drawn based on the shape? Shrink the shape, stroke shrinks with it, right? – Confused Sep 23 '16 at 15:25
  • @Confused That's the whole point of this. That's part of what creates the effect of having the whole stroke inside the shape – Nik Sep 23 '16 at 15:26
  • If the outline/stroke shrinks WITH the shape, it's not going to change the problem of it being part way over the shape, and partway outside the shape. The stroke will move with the size of the shape, right? – Confused Sep 23 '16 at 15:29
  • The stroke is a property of the shape. You can't separate it from the shape. So when you shrink the shape, the stroke moves with the outline of the shape. It doesn't change its state of being inside, centered or outside the shape... its always centered. There isn't an option to move or scale the stroke separate from the shape. – Confused Sep 23 '16 at 15:31
  • @Confused I see what you saying and you're correct, however even though it's still half inside and half outside the shape, shrinking the shape makes the stroke look like it's fully inside the ORIGINALLY sized shape. – Nik Sep 23 '16 at 15:32
  • I've added an image to the question to show the problem. – Confused Sep 23 '16 at 15:40
  • refresh the page. It's a dark grey background with three circles, each with the same weight of outline, centred, and red internals, blue outline that goes purple on the overlap area. – Confused Sep 23 '16 at 15:46
  • here's the shortlink: http://i.stack.imgur.com/AF7FO.png – Confused Sep 23 '16 at 15:47
  • @Confused The colour blends like that because you have an alpha of less than 1 for your stroke. This trick doesn't fully work with that because you get the result you have. The shape and stroke are changed, it just doesn't appear like it made a difference because you still notice the blending. I updated my answer – Nik Sep 23 '16 at 15:50
  • Yes, you're providing a "trick" to give the desired "visual" result. But the question, he's wanting it inside the shape, fully. That's a specific problem. – Confused Sep 23 '16 at 16:00
  • @Confused The solution looks and reacts as if it's inside the shape and it's an unnoticeable change for the user – Nik Sep 23 '16 at 16:01
  • This isn't about the user, it's about the question. There are other reasons to want an outline to be entirely within a shape, actually within the shape, not faking it. – Confused Sep 23 '16 at 16:01
  • @Confused Like what? By the way, I don't think there is a way to put a stroke on the inside or outside of a shape. That's why there's no easy solution to this – Nik Sep 23 '16 at 16:03
  • here's an example with a simple shape where faking it fails: http://i.stack.imgur.com/HI1a3.png – Confused Sep 23 '16 at 16:05
  • With a complex shape, failings of faking an internal outline become a huge problem very quickly. Imagine the sharp and complex corners of a letter, for example. – Confused Sep 23 '16 at 16:06
  • 1
    "By the way, I don't think there is a way to put a stroke on the inside or outside of a shape. That's why there's no easy solution to this" I think this is the answer to the question, then. It might not be possible in SpriteKit – Confused Sep 23 '16 at 16:06
  • I've long contended that Sprite Kit is not much more than a wrapper and addition of game loop to Core Animation. That's definitely the case with SKShapeNode, it's almost certainly a wrapped version of CAShapeLayer: http://stackoverflow.com/questions/18006801/why-does-a-cashapelayers-stroke-extend-out-of-the-frame – Confused Sep 23 '16 at 16:09
  • @Confused I understand what you're saying, but I really don't think there's any other way to do this without faking it... Unless you create a duplicate shape that also looks like a stroke... – Nik Sep 23 '16 at 16:11
  • Could a shader be used to create an internal stroke? – Confused Sep 23 '16 at 16:14
  • @Confused I'm not sure. I'm not familiar with shaders – Nik Sep 23 '16 at 16:16
  • @Confused I'm going to leave my answer here just because there isn't another proper solution, however if you or someone finds a proper solution, I will take mine down – Nik Sep 23 '16 at 16:18
  • I don't think there's ever going to be a need to delete your answer. For those for whom a "cheat" works, your approach might well be the answer. But the fuller extent of this problem is something that's plagued design programs for decades. – Confused Sep 23 '16 at 17:53
  • @Confused I agree. Thanks for bringing this to my attention – Nik Sep 23 '16 at 18:10
  • @Confused, does SKShapeNode allow shaders? Thought that was SceneKit only – Knight0fDragon Sep 26 '16 at 01:32
  • @Nik, just thought of an alternative, but it is less efficient then your answer, so please keep this one – Knight0fDragon Sep 26 '16 at 01:40
1

Just thought of an alternative to handle the more complex shapes.

Instead of shrinking the shape, we double the stroke size, so 6 now becomes 12. This will give us 6 on the outside and 6 on the inside.

We use SKCropNode, with a mask of our shape before stroke, then add the shape as a child. This should give us the results we want.

This should work for every scenario, like if we want stroke 2 on outside and 4 on the inside, we give our shape a stroke of 8, and we give our mask shape a stroke of 4

Note I have not tested this out, this is all thought out in my head.

Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44