当前位置:C++技术网 > 精选软件 > GDI渐变:1 斜向颜色渐变的黑线黑点问题探究分析和解决方案

GDI渐变:1 斜向颜色渐变的黑线黑点问题探究分析和解决方案

更新时间:2016-11-04 22:57:34浏览次数:1+次

    之前在实现斜向颜色渐变时,遇到一个问题,即:斜向颜色渐变的黑线黑点问题。

    先来看看斜向渐变效果:

斜向颜色渐变的黑线黑点问题探究分析和解决方案

【30度斜向渐变色】

斜向颜色渐变的黑线黑点问题探究分析和解决方案

【45度斜向渐变】

60度斜向渐变,出现了大量黑点和黑线

【60度斜向渐变,出现了大量黑点和黑线】

80度斜向渐变,比较少的黑点黑线

【80度斜向渐变,比较少的黑点黑线】

87度斜向渐变,少量黑点黑线

【87度斜向渐变,少量黑点黑线】

90度即水平渐变,无 黑点黑线

【90度即水平渐变,无 黑点黑线】

   由上面一系列图可以看到,当角度不断变大的时候,问题开始出现了。通过实际测试,超过45度之后,在60度左右最为严重。然后慢慢黑线黑点变少。直到90的水平渐变恢复正常。

    这是观察到的基本现象。虽然有渐变色了,可是有了黑线,那怎么行!为了解决这个问题,开始探索吧!!

    因为这个斜线的起始和结束坐标都是通过X轴的坐标值不断增加,然后通过三角函数tan来计算得到Y轴坐标值,然后画斜线。大量的斜线不断的叠加,也就形成了斜向渐变的效果。当然,颜色值是随着X轴坐标值变大而不断的渐变,每一条线一个颜色。

    一开始毫无头绪,【ooklasd】认为是三角函数在计算的时候,导致有些坐标值得不到,也就是说,线条画不到一些位置,才产生了黑线黑点。好像有点道理,但是没有确切的证据,难以说服我。

    在实现斜向渐变色的效果时,后面几天公司项目赶得很,所以暂停了下。然后昨晚回来竟然找到问题所在了。下面来分析一下过程。希望这个过程可以给你一些启发。遇到问题不能靠猜,而是要靠理性的分析,这样就可以比较顺利的确定问题所在。

    开始以为是三角函数计算问题,但是我是真找不到哪里算错了。找不到突破口,那就另寻他径吧。仔细分析现象,来找问题。

    虽然出现了黑线,但是这些渐变都很正常的渐变了。只是角度大了之后出现了黑线而已。一直以为自己数学不好,但是这个简单的三角函数应用不至于也搞不定吧。根据现象,超过45度角之后,开始出现黑线黑点,而tan函数在45度时为1,。然后角度继续增大,tan的值大于1。在0-90之间,不含0和90度,不可能得不到合适的Y轴坐标。

    我查了一下tan的曲线,下面是tan曲线:

tan函数曲线

【tan函数曲线】

   既然能够得到正常的tan值,那么一定可以计算到正确的Y轴坐标。所以,不是计算的问题。更何况,渐变色都有了,如果线条不能完整跨越整个画面,那么渐变色就不会正常显示。因为这些黑线黑点有很多是出现在中间的离散区域。

    到此,三角函数计算错误的可能被排除了。渐变色可以正常渐变,表明我的计算过程和实现都是正确的。那多出的黑线黑点到底是怎么回事呢?黑点黑线的多少的规律和tan曲线有点像的错觉被排除,那还有什么线索呢?似乎陷入了绝境,无从下手了。我再想,难道这是神秘的数学问题吗?我要放弃了吗?然而,就这样放弃了,太可惜了。完美的渐变,被黑线黑点给打败了。不过,战斗才刚刚开始,我不能放弃,也绝对不甘心。我要实现的渐变,一定要实现!!只有在细心的寻找问题了。我不能被以为的数学很差这个借口打败,不能为自己找借口。

    写程序找问题和解数学方程式不一样的地方,也正是我喜欢的地方,那就是尝试!!数学的演算推导太累了,而且一步出错,全盘皆输。而写程序可以迅速验证,尝试的周期很短,很快可以出结果。这样可以在短时间内进行大量的试验。大量的试验得到的结果都可以作为现象来反馈,帮助思考。

    所以我鼓起勇气,向我“数学不好”这个借口发起挑战!!试试看,总会发现精彩的。反正试一下又不要钱。

    仔细看了下代码,除了计算坐标的位置,还有其他可以改变的因素,比如颜色值,比如线的粗细。其实改变的东西不多,但是很显然,线条的粗细被我盯上了。要不改变一下线条的粗细试试。原先线条宽度是1,然后我改为3试试,看看什么效果。在尝试的时候,我不用在内心演算效果,直接改变之后,看看是什么效果就好了,而这个效果,因为没有预先演算,所以对我来说,是未知的,是可期待的。运行的那一刻,屏住呼吸,就等待一个结果。可能让人沮丧,可能让人惊喜,可能让人觉得平淡无奇。不管怎么样,就是这样的不确定性,世界才精彩。

    我将线条宽度改为3,然后运行了一下。神奇的情况出现了,在60度的时候,到处的黑线黑点竟然不见了。那一刻好开心!!但是,我怕这是昙花一现,怕稍纵即逝。赶紧,改一下角度,不管是30、50、60、70、80、87,这些角度全部都没有黑线黑点了,压制着心中的兴奋,继续验证。就怕高兴的太早,所以要严谨的测试结果。我又质疑画面小了是不是黑线黑点不明显了。然后全屏,改变大小,绘制渐变色,不管怎么玩,都没有黑线黑点了。哈哈哈哈,终于解决了这个问题。而解决办法,不过就是增加了一下线条的宽度。那一刻,彻底可以放开心兴奋了。那一刻,不知道与谁分享这份开心。我很庆幸,工作三年多了,依然能够保持这样的兴趣,保持这份纯真的开心和兴奋。

    我很快将这个消息发到了C++技术网的两个群,分享到了空间、朋友圈。但是因为问题还需要进一步研究,所以,只简单研究了一下,然后分享出去了。
    其实,很多时候,看似无解的问题,就在于这么一个简单的尝试,只要你愿意跨出这一步,而不是在那里绝望,希望总会出现的让你惊讶,让你喜出望外!但是,这些绝对不是偶尔,是你的努力让这一切变得真实了。我们很多时候,总会遇到各种问题,如果你迟疑了,或许就隔着一步之遥,你就永远找不到答案了。

    那么本文已经从问题的出现,到分析,到最后尝试解决了,整过过程都写出来了。希望能够大家一个启发,给大家信心,在今后写代码的时候,能够勇敢,耐心细心的去分析,去尝试,不要有任何的抱怨、埋怨和借口。

    虽然问题解决了,但是是不是解决到位了,还需要验证。所以,要真正解决问题,要真正放心,就需要彻底验证问题,这样才算是真正解决了问题。很多时候,表面上看似解决了,实际上,可能只是暂时避开了问题,定时炸弹埋下了,指不定什么时候就触发了。所以,验证问题也是非常关键的。

    可能简单的解决问题,是大多数人的做法。而一个负责人、一个求知欲强烈的人、一个追求完美解决问题的人,一个合格的程序员,一定要去认真的验证问题。只有验证通过,才算问题解决完毕。在我第一年工作的时候,维护代码,解决问题,我同事跟我说,一定要找到根本问题,真正解决问题,而否定了我找到的几个问题。

    那时候我很无奈,难道我找的问题,就不是根本问题吗?后来想想,我只是找到了问题触发的那个点,然后就以为找到了问题。到现在来看,找到问题,一定要让问题反复可以复现,可以让问题针对性解决,可以符合所有的现象。而不是表面的掩盖问题。

    好了,这个问题的探索就到这了。回头再写一个问题验证的分析过程,和找问题一样精彩,期待吧。